// bdldfp_decimalimputil.t.cpp                                        -*-C++-*-
#include <bdldfp_decimalimputil.h>

#include <bslim_testutil.h>

#include <bslma_testallocator.h>
#include <bslma_defaultallocatorguard.h>

#include <bsls_assert.h>
#include <bsls_asserttest.h>
#include <bsls_stopwatch.h>

#include <bsl_algorithm.h>
#include <bsl_climits.h>
#include <bsl_cmath.h>
#include <bsl_cstdlib.h>
#include <bsl_limits.h>
#include <bsl_iostream.h>
#include <bsl_sstream.h>
#include <bsl_string.h>

#include <typeinfo>

using namespace BloombergLP;
using bsl::cout;
using bsl::cerr;
using bsl::flush;
using bsl::endl;
using bsl::atoi;

// ============================================================================
//                                 TEST PLAN
// ----------------------------------------------------------------------------
//                                  Overview
//                                  --------
// TBD:
// ----------------------------------------------------------------------------
// CLASS METHODS
// [13] makeDecimal64(                   int, int)
// [13] makeDecimal64(unsigned           int, int)
// [13] makeDecimal64(         long long int, int)
// [13] makeDecimal64(unsigned long long int, int)
// [12] makeInfinity64(bool)
// [14]  int32ToDecimal32 (                   int)
// [14] uint32ToDecimal32 (unsigned           int)
// [14]  int64ToDecimal32 (         long long int)
// [14] uint64ToDecimal32 (unsigned long long int)
// [14]  int32ToDecimal64 (                   int)
// [14] uint32ToDecimal64 (unsigned           int)
// [14]  int64ToDecimal64 (         long long int)
// [14] uint64ToDecimal64 (unsigned long long int)
// [14]  int32ToDecimal128(                   int)
// [14] uint32ToDecimal128(unsigned           int)
// [14]  int64ToDecimal128(         long long int)
// [14] uint64ToDecimal128(unsigned long long int)
// [ 5] add(ValueType32,  ValueType32)
// [ 5] add(ValueType64,  ValueType64)
// [ 5] add(ValueType128, ValueType128)
// [ 6] subtract(ValueType32,  ValueType32)
// [ 6] subtract(ValueType64,  ValueType64)
// [ 6] subtract(ValueType128, ValueType128)
// [ 7] multiply(ValueType32,  ValueType32)
// [ 7] multiply(ValueType64,  ValueType64)
// [ 7] multiply(ValueType128, ValueType128)
// [ 8] divide(ValueType32,  ValueType32)
// [ 8] divide(ValueType64,  ValueType64)
// [ 8] divide(ValueType128, ValueType128)
// [ 9] negate(ValueType32)
// [ 9] negate(ValueType64)
// [ 9] negate(ValueType128)
// [16] less(ValueType32,  ValueType32)
// [16] less(ValueType64,  ValueType64)
// [16] less(ValueType128, ValueType128)
// [16] greater(ValueType32,  ValueType32)
// [16] greater(ValueType64,  ValueType64)
// [16] greater(ValueType128, ValueType128)
// [16] lessEqual(ValueType32,  ValueType32)
// [16] lessEqual(ValueType64,  ValueType64)
// [16] lessEqual(ValueType128, ValueType128)
// [16] greaterEqual(ValueType32,  ValueType32)
// [16] greaterEqual(ValueType64,  ValueType64)
// [16] greaterEqual(ValueType128, ValueType128)
// [ 3] equal(ValueType32,  ValueType32)
// [ 3] equal(ValueType64,  ValueType64)
// [ 3] equal(ValueType128, ValueType128)
// [ 4] notEqual(ValueType32,  ValueType32)
// [ 4] notEqual(ValueType64,  ValueType64)
// [ 4] notEqual(ValueType128, ValueType128)
// [10] convertToDecimal32( const ValueType64&)
// [10] convertToDecimal32( const ValueType128&)
// [10] convertToDecimal64( const ValueType32&)
// [10] convertToDecimal64( const ValueType128&)
// [10] convertToDecimal128(const ValueType32&)
// [10] convertToDecimal128(const ValueType64&)
// [15] binaryToDecimal32 (float)
// [15] binaryToDecimal32 (double)
// [15] binaryToDecimal64 (float)
// [15] binaryToDecimal64 (double)
// [15] binaryToDecimal128(float)
// [15] binaryToDecimal128(double)
// [ 2] makeDecimalRaw32 (                   int, int)
// [ 2] makeDecimalRaw64 (unsigned long long int, int)
// [ 2] makeDecimalRaw64 (         long long int, int)
// [ 2] makeDecimalRaw64 (unsigned           int, int)
// [ 2] makeDecimalRaw64 (                   int, int)
// [ 2] makeDecimalRaw128(unsigned long long int, int)
// [ 2] makeDecimalRaw128(         long long int, int)
// [ 2] makeDecimalRaw128(unsigned           int, int)
// [ 2] makeDecimalRaw128(                   int, int)
// [17] scaleB(ValueType32,  int)
// [17] scaleB(ValueType64,  int)
// [17] scaleB(ValueType128, int)
// [18] int format(char *, int, ValueType32,  const DecimalFormatConfig&);
// [18] int format(char *, int, ValueType64,  const DecimalFormatConfig&);
// [18] int format(char *, int, ValueType128, const DecimalFormatConfig&);
// [11] parse32 (const char *)
// [11] parse64 (const char *)
// [11] parse128(const char *)
// [ 1] checkLiteral(double)
// [20] convertDPDtoBID(DenselyPackedDecimalImpUtil::StorageType32)
// [20] convertDPDtoBID(DenselyPackedDecimalImpUtil::StorageType64)
// [20] convertDPDtoBID(DenselyPackedDecimalImpUtil::StorageType128)
// [19] convertBIDtoDPD(ValueType32)
// [19] convertBIDtoDPD(ValueType64)
// [19] convertBIDtoDPD(ValueType128)
// [22] convertFromBID(BinaryIntegralDecimalImpUtil::StorageType32)
// [22] convertFromBID(BinaryIntegralDecimalImpUtil::StorageType64)
// [22] convertFromBID(BinaryIntegralDecimalImpUtil::StorageType128)
// [21] convertToBID(ValueType32)
// [21] convertToBID(ValueType64)
// [21] convertToBID(ValueType128)
// [25] int classify(ValueType32  x);
// [25] int classify(ValueType64  x);
// [25] int classify(ValueType128 x);
// [26] ValueType32 normalize(ValueType32 original);
// [26] ValueType64 normalize(ValueType64 original);
// [26] ValueType128 normalize(ValueType128 original);
// [24] int decompose(int *, unsigned int *, int *, ValueType32);
// [24] int decompose(int *, bsls::Types::Uint64 *, int *, ValueType64);
// [24] int decompose(int *, Uint128 *, int *, ValueType128);
// [23] ValueType32 min32();
// [23] ValueType32 max32();
// [23] ValueType32 epsilon32();
// [23] ValueType32 roundError32();
// [23] ValueType32 denormMin32();
// [23] ValueType32 infinity32();
// [23] ValueType32 quietNaN32();
// [23] ValueType32 signalingNaN32();
// [23] ValueType64 min64();
// [23] ValueType64 max64();
// [23] ValueType64 epsilon64();
// [23] ValueType64 roundError64();
// [23] ValueType64 denormMin64();
// [23] ValueType64 infinity64();
// [23] ValueType64 quietNaN64();
// [23] ValueType64 signalingNaN64();
// [23] ValueType128 min128();
// [23] ValueType128 max128();
// [23] ValueType128 epsilon128();
// [23] ValueType128 roundError128();
// [23] ValueType128 denormMin128();
// [23] ValueType128 infinity128();
// [23] ValueType128 quietNaN128();
// [23] ValueType128 signalingNaN128();
// [27] ValueType32  copySign(ValueType32);
// [27] ValueType64  copySign(ValueType64);
// [27] ValueType128 copySign(ValueType128);
// [27] ValueType32  exp(ValueType32);
// [27] ValueType64  exp(ValueType64);
// [27] ValueType128 exp(ValueType128);
// [27] ValueType32  log(ValueType32);
// [27] ValueType64  log(ValueType64);
// [27] ValueType128 log(ValueType128);
// [27] ValueType32  logB(ValueType32);
// [27] ValueType64  logB(ValueType64);
// [27] ValueType128 logB(ValueType128);
// [27] ValueType32  log10(ValueType32);
// [27] ValueType64  log10(ValueType64);
// [27] ValueType128 log10(ValueType128);
// [27] ValueType32  ceil(ValueType32);
// [27] ValueType64  ceil(ValueType64);
// [27] ValueType128 ceil(ValueType128);
// [27] ValueType32  fmod(ValueType32,  ValueType32);
// [27] ValueType64  fmod(ValueType64,  ValueType64);
// [27] ValueType128 fmod(ValueType128, ValueType128);
// [27] ValueType32  remainder(ValueType32,  ValueType32);
// [27] ValueType64  remainder(ValueType64,  ValueType64);
// [27] ValueType128 remainder(ValueType128, ValueType128);
// [27] long int lrint(ValueType32);
// [27] long int lrint(ValueType64);
// [27] long int lrint(ValueType128);
// [27] long long int llrint(ValueType32);
// [27] long long int llrint(ValueType64);
// [27] long long int llrint(ValueType128);
// [27] ValueType32  nextafter(ValueType32,  ValueType32);
// [27] ValueType64  nextafter(ValueType64,  ValueType64);
// [27] ValueType128 nextafter(ValueType128, ValueType128);
// [27] ValueType32  nexttoward(ValueType32 , ValueType32);
// [27] ValueType64  nexttoward(ValueType64,  ValueType64);
// [27] ValueType128 nexttoward(ValueType128, ValueType128);
// [27] ValueType32  pow(ValueType32);
// [27] ValueType64  pow(ValueType64);
// [27] ValueType128 pow(ValueType128);
// [27] long int lround(ValueType32);
// [27] long int lround(ValueType64);
// [27] long int lround(ValueType128);
// [27] ValueType32  sqrt(ValueType32);
// [27] ValueType64  sqrt(ValueType64);
// [27] ValueType128 sqrt(ValueType128);
// [27] ceil(ValueType32)
// [27] ceil(ValueType64)
// [27] ceil(ValueType128)
// [27] floor(ValueType32)
// [27] floor(ValueType64)
// [27] floor(ValueType128)
// [27] trunc(ValueType32)
// [27] trunc(ValueType64)
// [27] trunc(ValueType128)
// [27] round(ValueType32)
// [27] round(ValueType64)
// [27] round(ValueType128)
// [27] fabs(ValueType32)
// [27] fabs(ValueType64)
// [27] fabs(ValueType128)
// [28] fma(ValueType32,  ValueType32,  ValueType32);
// [28] fma(ValueType64,  ValueType64,  ValueType64);
// [28] fma(ValueType128, ValueType128, ValueType128);
// [29] quantize(ValueType32,    ValueType32);
// [29] quantize(ValueType64,    ValueType64);
// [29] quantize(ValueType128,   ValueType128);
// [29] quantize(ValueType32,    int);
// [29] quantize(ValueType64,    int);
// [29] quantize(ValueType128,   int);
// [29] quantizeEqual(ValueType32  *, ValueType32,  int);
// [29] quantizeEqual(ValueType64  *, ValueType64,  int);
// [29] quantizeEqual(ValueType128 *, ValueType128, int);
// [30] sameQuantum(ValueType32,  ValueType32);
// [30] sameQuantum(ValueType64,  ValueType64);
// [30] sameQuantum(ValueType128, ValueType128);
// ----------------------------------------------------------------------------
// [ 1] BREATHING TEST
// [ 4] TEST 'notEqual' FOR 'NaN' CORRECTNESS
// [32] USAGE EXAMPLE
// ----------------------------------------------------------------------------

//=============================================================================
//                    STANDARD BDE ASSERT TEST MACRO
//-----------------------------------------------------------------------------

namespace {

int testStatus = 0;

void aSsErT(bool b, const char *s, int i)
{
    if (b) {
        cout << "Error " << __FILE__ << "(" << i << "): " << s
             << "    (failed)" << endl;
        if (0 <= testStatus && testStatus <= 100) ++testStatus;
    }
}

}  // close unnamed namespace

//=============================================================================
//                       STANDARD BDE TEST DRIVER MACROS
//-----------------------------------------------------------------------------

#define ASSERT       BSLIM_TESTUTIL_ASSERT
#define LOOP_ASSERT  BSLIM_TESTUTIL_LOOP_ASSERT
#define LOOP0_ASSERT BSLIM_TESTUTIL_LOOP0_ASSERT
#define LOOP1_ASSERT BSLIM_TESTUTIL_LOOP1_ASSERT
#define LOOP2_ASSERT BSLIM_TESTUTIL_LOOP2_ASSERT
#define LOOP3_ASSERT BSLIM_TESTUTIL_LOOP3_ASSERT
#define LOOP4_ASSERT BSLIM_TESTUTIL_LOOP4_ASSERT
#define LOOP5_ASSERT BSLIM_TESTUTIL_LOOP5_ASSERT
#define LOOP6_ASSERT BSLIM_TESTUTIL_LOOP6_ASSERT
#define ASSERTV      BSLIM_TESTUTIL_ASSERTV

#define Q            BSLIM_TESTUTIL_Q   // Quote identifier literally.
#define P            BSLIM_TESTUTIL_P   // Print identifier and value.
#define P_           BSLIM_TESTUTIL_P_  // P(X) without '\n'.
#define T_           BSLIM_TESTUTIL_T_  // Print a tab (w/o newline).
#define L_           BSLIM_TESTUTIL_L_  // current Line number

// ============================================================================
//                  NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT_SAFE_PASS(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_PASS(EXPR)
#define ASSERT_SAFE_FAIL(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_FAIL(EXPR)
#define ASSERT_PASS(EXPR)      BSLS_ASSERTTEST_ASSERT_PASS(EXPR)
#define ASSERT_FAIL(EXPR)      BSLS_ASSERTTEST_ASSERT_FAIL(EXPR)
#define ASSERT_OPT_PASS(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_PASS(EXPR)
#define ASSERT_OPT_FAIL(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_FAIL(EXPR)

// ============================================================================
//                  GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------

namespace BDEC = BloombergLP::bdldfp;

typedef BDEC::DecimalImpUtil      Util;
typedef BDEC::DecimalFormatConfig Config;
typedef BDEC::DecimalStorage      DS;

const long long mantissas[] = {
                                               0LL,
                                               2LL,
                                               7LL,
                                              35LL,
                                              72LL,
                                             135LL,
                                             924LL,

                  // Exhaustive mantissa cases
                                               1LL,
                                               9LL,
                                              12LL,
                                              98LL,
                                             123LL,
                                             987LL,
                                            1234LL,
                                            9876LL,
                                           12345LL,
                                           98765LL,
                                          123456LL,
                                          987654LL,
                                         1234567LL,
                                         9876543LL,
                                        12345678LL,
                                        98765432LL,
                                       123456789LL,
                                       987654321LL,
                                      1234567890LL,
                                      9876543210LL,
                                     12345678901LL,
                                     98765432109LL,
                                    123456789012LL,
                                    987654321098LL,
                                   1234567890123LL,
                                   9876543210987LL,
                                  12345678901234LL,
                                  98765432109876LL,
                                 123456789012345LL,
                                 987654321098765LL,
                                1234567890123456LL,
                                9876543210987654LL,

                               -               1LL,
                               -               9LL,
                               -              12LL,
                               -              98LL,
                               -             123LL,
                               -             987LL,
                               -            1234LL,
                               -            9876LL,
                               -           12345LL,
                               -           98765LL,
                               -          123456LL,
                               -          987654LL,
                               -         1234567LL,
                               -         9876543LL,
                               -        12345678LL,
                               -        98765432LL,
                               -       123456789LL,
                               -       987654321LL,
                               -      1234567890LL,
                               -      9876543210LL,
                               -     12345678901LL,
                               -     98765432109LL,
                               -    123456789012LL,
                               -    987654321098LL,
                               -   1234567890123LL,
                               -   9876543210987LL,
                               -  12345678901234LL,
                               -  98765432109876LL,
                               - 123456789012345LL,
                               - 987654321098765LL,
                               -1234567890123456LL,
                               -9876543210987654LL
                              };
const int numMantissas = static_cast<int>(
                                       sizeof(mantissas) / sizeof(*mantissas));

const int exponents[] = {
                            0,
                            1,
                            7,
                           13,
                           64,
                          123,
                          321,

                         -  1,
                         -  7,
                         - 13,
                         - 64,
                         -123,
                         -321
                        };
const int numExponents = static_cast<int>(
                                       sizeof(exponents) / sizeof(*exponents));


static const long long TEST_NONZERO_MANTISSAS[] = {
    // These numbers will test equality of decimal floating point values of
    // different quanta.
    2LL,
    7LL,
    20LL,
    70LL,
    200LL,
    700LL,
    2000LL,
    7000LL,
    20000LL,
    70000LL,
    200000LL,
    700000LL,
    2000000LL,
    7000000LL,
    20000000LL,
    70000000LL,
    200000000LL,
    700000000LL,
    2000000000LL,
    7000000000LL,
    20000000000LL,
    70000000000LL,
    200000000000LL,
    700000000000LL,
    2000000000000LL,
    7000000000000LL,
    20000000000000LL,
    70000000000000LL,
    200000000000000LL,
    700000000000000LL,
    2000000000000000LL,
    7000000000000000LL,
    20000000000000000LL,
    70000000000000000LL,
    200000000000000000LL,
    700000000000000000LL,

    // These number ensure that we can handle digits in all positions of the
    // mantissa.
    12LL,
    123LL,
    1234LL,
    12345LL,
    123456LL,
    1234567LL,
    12345678LL,
    123456789LL,
    1234567890LL,
    12345678901LL,
    123456789012LL,
    1234567890123LL,
    12345678901234LL,
    123456789012345LL,
    1234567890123456LL,
    12345678901234567LL,
    123456789012345678LL,
    1234567890123456789LL,

    // These numbers test the behavior of rounding to 16 significant figures
    // (e.g., in makeDecimal64.)
    44444444444444444LL,
    44444444444444445LL,
    44444444444444455LL,
    444444444444444444LL,
    444444444444444445LL,
    444444444444444455LL,
    4444444444444444445LL,
    4444444444444444455LL,
    4444444444444444555LL,
    5555555555555555555LL,

    // Negative variations of these test numbers.
    -2LL,
    -7LL,
    -20LL,
    -70LL,
    -200LL,
    -700LL,
    -2000LL,
    -7000LL,
    -20000LL,
    -70000LL,
    -200000LL,
    -700000LL,
    -2000000LL,
    -7000000LL,
    -20000000LL,
    -70000000LL,
    -200000000LL,
    -700000000LL,
    -2000000000LL,
    -7000000000LL,
    -20000000000LL,
    -70000000000LL,
    -200000000000LL,
    -700000000000LL,
    -2000000000000LL,
    -7000000000000LL,
    -20000000000000LL,
    -70000000000000LL,
    -200000000000000LL,
    -700000000000000LL,
    -2000000000000000LL,
    -7000000000000000LL,
    -20000000000000000LL,
    -70000000000000000LL,
    -200000000000000000LL,
    -700000000000000000LL,
    -12LL,
    -123LL,
    -1234LL,
    -12345LL,
    -123456LL,
    -1234567LL,
    -12345678LL,
    -123456789LL,
    -1234567890LL,
    -12345678901LL,
    -123456789012LL,
    -1234567890123LL,
    -12345678901234LL,
    -123456789012345LL,
    -1234567890123456LL,
    -12345678901234567LL,
    -123456789012345678LL,
    -1234567890123456789LL,

    -44444444444444444LL,
    -44444444444444445LL,
    -44444444444444455LL,
    -444444444444444444LL,
    -444444444444444445LL,
    -444444444444444455LL,
    -4444444444444444445LL,
    -4444444444444444455LL,
    -4444444444444444555LL,
    -5555555555555555555LL,

};

const int NUM_TEST_NONZERO_MANTISSAS = static_cast<int>(
               sizeof TEST_NONZERO_MANTISSAS / sizeof *TEST_NONZERO_MANTISSAS);

static const int TEST_EXPONENTS[] = {
    -4064,
    -399,
    -398,
    -355,
    -44,
    -42,
    -13,
    -4,
    -3,
    -2,
    -1,
    0,
    1,
    2,
    3,
    4,
    13,
    42,
    44,
    355,

    // These exponents exercise the rounding behavior of makeDecimal64.
    369,
    370,
    371,
    372,
    373,
    374,
    375,
    376,
    377,
    378,
    379,
    380,
    381,
    382,
    383,
    384,
    385,

    4064
};

const int NUM_TEST_EXPONENTS = static_cast<int>(
                               sizeof TEST_EXPONENTS / sizeof *TEST_EXPONENTS);

#define MAX_DECIMAL_32                                                    \
 "9999999000""0000000000""0000000000""0000000000""0000000000"             \
 "0000000000""0000000000""0000000000""0000000000""0000000"

#define MIN_DECIMAL_32                                                    \
 "0.00000000""0000000000""0000000000""0000000000""0000000000"             \
 "0000000000""0000000000""0000000000""0000000000""0000001"

#define SUBNORMAL_DECIMAL_32                                              \
 "0.00000000""0000000000""0000000000""0000000000""0000000000"             \
 "0000000000""0000000000""0000000000""0000000000""0000000000""001"

#define MAX_DECIMAL_64                                                    \
 "9999999999""9999990000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""00000"

#define MIN_DECIMAL_64                                                    \
 "0.00000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""00001"

#define SUBNORMAL_DECIMAL_64                                              \
 "0.00000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000001"

#define MAX_DECIMAL_128                                                   \
 "9999999999""9999999999""9999999999""9999000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""00000"

 #define MIN_DECIMAL_128                                                  \
 "0.00000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""00001"

 #define SUBNORMAL_DECIMAL_128                                            \
 "0.00000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""0000000000" \
 "0000000000""0000000000""0000000000""0000000000""0000000000""00000001"

// ============================================================================
//                      HELPER FUNCTIONS FOR TESTING
// ----------------------------------------------------------------------------

template<class INTEGER>
bsl::string makeParseString(INTEGER mantissa, int exponent)
    // Return a string representing the specified 'mantissa' and 'exponent', in
    // the format 'MeX', where 'M' is a string representation of 'mantissa',
    // and 'X' is a string representation of 'exponent'.  Note that this
    // function is intended to reduce the complexity of the 'makeDecimalRawXX'
    // test cases.
{
    bsl::ostringstream oss;
    oss << mantissa << "e" << exponent;
    return oss.str();
}

bool nanEqual(Util::ValueType32 lhs, Util::ValueType32 rhs)
    // Return true if the specified 'lhs' and 'rhs' are the same value, even in
    // the case of 'NaN'.  Two 'ValueType32' objects are considered equal if
    // either 'Util::equal' returns true, or both 'lhs' and 'rhs' are not equal
    // to themselves (implying them both to be 'NaN').
{
    return  Util::equal(lhs, rhs)
        || (Util::notEqual(lhs, lhs) && Util::notEqual(rhs, rhs));
}

bool nanEqual(Util::ValueType64 lhs, Util::ValueType64 rhs)
    // Return true if the specified 'lhs' and 'rhs' are the same value, even in
    // the case of 'NaN'.  Two 'ValueType64' objects are considered equal if
    // either 'Util::equal' returns true, or both 'lhs' and 'rhs' are not equal
    // to themselves (implying them both to be 'NaN').
{
    return  Util::equal(lhs, rhs)
        || (Util::notEqual(lhs, lhs) && Util::notEqual(rhs, rhs));
}

bool nanEqual(Util::ValueType128 lhs, Util::ValueType128 rhs)
    // Return true if the specified 'lhs' and 'rhs' are the same value, even in
    // the case of 'NaN'.  Two 'ValueType128' objects are considered equal if
    // either 'Util::equal' returns true, or both 'lhs' and 'rhs' are not equal
    // to themselves (implying them both to be 'NaN').
{
    return  Util::equal(lhs, rhs)
        || (Util::notEqual(lhs, lhs) && Util::notEqual(rhs, rhs));
}

template <class DECIMAL>
inline
bool isNaN(DECIMAL value)
    // Return true if the specified 'value' is NaN, and false otherwise.
{
    return Util::notEqual(value, value);
}

template <class TYPE>
bool checkBitsEquality(TYPE lhs, TYPE rhs)
    // Return 'true' if binary representations of the specified 'lhs' and 'rhs'
    // are equal and 'false' otherwise.
{
    return 0 == bsl::memcmp(&lhs, &rhs, sizeof(TYPE));
}

template <class DECIMAL>
struct DecimalFactory;
    // This 'struct' template provides a mechanism to create an object of the
    // template parameter type 'DECIMAL' through a consistent interface.

template <>
struct DecimalFactory<Util::ValueType32>
    // This template specialization of 'DecimalFactory' provides functions to
    // create 'ValueType32' values.
{
    typedef int Significand;
    typedef int Exponent;

    static Util::ValueType32 makeDecimalRaw(Significand significand,
                                            Exponent    exponent)
        // Create a 'ValueType32' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.
    {
        return Util::makeDecimalRaw32(significand, exponent);
    }

    static Util::ValueType32 infinity()
        // Return the value that represents positive infinity for the
        // 'ValueType32' type.
    {
        return Util::infinity32();
    }

    static Util::ValueType32 quietNaN()
        // Return a value that represents non-signaling NaN for the
        // 'ValueType32' type.
    {
        return Util::quietNaN32();
    }

    static Util::ValueType32 signalingNaN()
        // Return a value that represents signaling NaN for the
        // 'ValueType32' type.
    {
        return Util::signalingNaN32();
    }
};

template <>
struct DecimalFactory<Util::ValueType64>
    // This template specialization of 'DecimalFactory' provides functions to
    // create 'ValueType64' values.
{
    typedef long long Significand;
    typedef int Exponent;

    static Util::ValueType64 makeDecimalRaw(Significand significand,
                                            Exponent    exponent)
        // Create a 'ValueType64' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.
    {
        return Util::makeDecimalRaw64(significand, exponent);
    }

    static Util::ValueType64 infinity()
        // Return the value that represents positive infinity for the
        // 'ValueType64' type.
    {
        return Util::infinity64();
    }

    static Util::ValueType64 quietNaN()
        // Return a value that represents non-signaling NaN for the
        // 'ValueType64' type.
    {
        return Util::quietNaN64();
    }

    static Util::ValueType64 signalingNaN()
        // Return a value that represents signaling NaN for the
        // 'ValueType64' type.
    {
        return Util::signalingNaN64();
    }
};

template <>
struct DecimalFactory<Util::ValueType128>
    // This template specialization of 'DecimalFactory' provides functions to
    // create 'ValueType128' values.
{
    typedef long long Significand;
    typedef int Exponent;

    static Util::ValueType128 makeDecimalRaw(Significand significand,
                                             Exponent    exponent)
        // Create a 'ValueType128' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.
    {
        return Util::makeDecimalRaw128(significand, exponent);
    }

    static Util::ValueType128 infinity()
        // Return the value that represents positive infinity for the
        // 'ValueType128' type.
    {
        return Util::infinity128();
    }

    static Util::ValueType128 quietNaN()
        // Return a value that represents non-signaling NaN for the
        // 'ValueType128' type.
    {
        return Util::quietNaN128();
    }

    static Util::ValueType128 signalingNaN()
        // Return a value that represents signaling NaN for the
        // 'ValueType128' type.
    {
        return Util::signalingNaN128();
    }
};


template <class DECIMAL>
void testFma()
    // ------------------------------------------------------------------------
    // TESTING FMA
    //
    // Concerns:
    //:  1 That 'fma(x, y, z)' to 'NaN' or 'Inf' should follow the IEEE rules
    //:    for the cases listed in the following charts:
    //:
    //:                   x * y|-Inf|Normal|+Inf|NaN|
    //:                  ------+----+------+----+---+
    //:                   -Inf |+Inf|+/-Inf|-Inf|NaN|
    //:                  ------+----+------+----+---+
    //:                  Normal| Inf|Normal| Inf|NaN|
    //:                  ------+----+------+----+---+
    //:                   +Inf |-Inf|+/-Inf|+Inf|NaN|
    //:                  ------+----+------+----+---+
    //:                    NaN | NaN|  NaN | NaN|NaN|
    //:
    //:             (x * y) + z|-Inf|Normal|+Inf|NaN|
    //:            ------------+----+------+----+---+
    //:                -Inf    |-Inf| -Inf | NaN|NaN|
    //:            ------------+----+------+----+---+
    //:               Normal   |-Inf|Normal|+Inf|NaN|
    //:            ------------+----+------+----+---+
    //:                +Inf    | NaN| +Inf |+Inf|NaN|
    //:            ------------+----+------+----+---+
    //:                 NaN    | NaN|  NaN | NaN|NaN|
    //
    // Plan:
    //:  1 Test all 64 special cases in the charts, which covers all
    //:    combination of input decimal value types (C-1)
    //
    // Testing
    //   fabs(ValueType32,  ValueType32,  ValueType32);
    //   fabs(ValueType64,  ValueType64,  ValueType64);
    //   fabs(ValueType128, ValueType128, ValueType128);
    // ------------------------------------------------------------------------
{
    typedef DecimalFactory<DECIMAL> Factory;

    const DECIMAL  INF_P  = Factory::infinity();
    const DECIMAL  INF_N  = Util::negate(INF_P);
    const DECIMAL  NaN    = Factory::quietNaN();
    const DECIMAL  sNAN   = Factory::signalingNaN();
    const DECIMAL  NORMAL = Factory::makeDecimalRaw(42, 0);
    const DECIMAL  ZERO   = Factory::makeDecimalRaw( 0, 0);

    ASSERT( Util::equal(INF_P, INF_P));
    ASSERT( Util::equal(INF_N, INF_N));
    ASSERT( Util::notEqual(INF_P, INF_N));
    ASSERT(!Util::equal(NaN, NaN));
    ASSERT( Util::notEqual(NaN, NaN));

    struct {
        int     d_line;
        DECIMAL d_x;
        DECIMAL d_y;
        DECIMAL d_z;
        DECIMAL d_expected;
        int     d_errno;
    } DATA[] = {
     //------------------------------------------------
     //LINE |   A  |   B   |   C    | EXPECTED
     //------------------------------------------------
        { L_, INF_N,  INF_N,  INF_N,  NaN,    EDOM },
        { L_, INF_N,  INF_N,  NORMAL, INF_P,     0 },
        { L_, INF_N,  INF_N,  INF_P,  INF_P,     0 },
        { L_, INF_N,  INF_N,  NaN,    NaN,       0 },

        { L_, INF_N,  NORMAL, INF_N,  INF_N,     0 },
        { L_, INF_N,  NORMAL, NORMAL, INF_N,     0 },
        { L_, INF_N,  NORMAL, INF_P,  NaN,    EDOM },
        { L_, INF_N,  NORMAL, NaN,    NaN,       0 },

        { L_, INF_N,  INF_P,  INF_N,  INF_N,     0 },
        { L_, INF_N,  INF_P,  NORMAL, INF_N,     0 },
        { L_, INF_N,  INF_P,  INF_P,  NaN,    EDOM },
        { L_, INF_N,  INF_P,  NaN,    NaN,       0 },

        { L_, INF_N,  NaN,    INF_N,  NaN,       0 },
        { L_, INF_N,  NaN,    NORMAL, NaN,       0 },
        { L_, INF_N,  NaN,    INF_P,  NaN,       0 },
        { L_, INF_N,  NaN,    NaN,    NaN,       0 },

        { L_, NORMAL, INF_N,  INF_N,  INF_N,     0 },
        { L_, NORMAL, INF_N,  NORMAL, INF_N,     0 },
        { L_, NORMAL, INF_N,  INF_P,  NaN,    EDOM },
        { L_, NORMAL, INF_N,  NaN,    NaN,       0 },

        { L_, NORMAL, NORMAL, INF_N,  INF_N,     0 },
        { L_, NORMAL, NORMAL, NORMAL, Factory::makeDecimalRaw(42*42+42, 0),
                                                 0 },
        { L_, NORMAL, NORMAL, INF_P,  INF_P,     0 },
        { L_, NORMAL, NORMAL, NaN,    NaN,       0 },

        { L_, NORMAL, INF_P,  INF_N,  NaN,    EDOM },
        { L_, NORMAL, INF_P,  NORMAL, INF_P,     0 },
        { L_, NORMAL, INF_P,  INF_P,  INF_P,     0 },
        { L_, NORMAL, INF_P,  NaN,    NaN,       0 },

        { L_, NORMAL, NaN,    INF_N,  NaN,       0 },
        { L_, NORMAL, NaN,    NORMAL, NaN,       0 },
        { L_, NORMAL, NaN,    INF_P,  NaN,       0 },
        { L_, NORMAL, NaN,    NaN,    NaN,       0 },

        { L_, INF_P,  INF_N,  INF_N,  INF_N,     0 },
        { L_, INF_P,  INF_N,  NORMAL, INF_N,     0 },
        { L_, INF_P,  INF_N,  INF_P,  NaN,    EDOM },
        { L_, INF_P,  INF_N,  NaN,    NaN,       0 },

        { L_, INF_P,  NORMAL, INF_N,  NaN,    EDOM },
        { L_, INF_P,  NORMAL, NORMAL, INF_P,     0 },
        { L_, INF_P,  NORMAL, INF_P,  INF_P,     0 },
        { L_, INF_P,  NORMAL, NaN,    NaN,       0 },

        { L_, INF_P,  INF_P,  INF_N,  NaN,    EDOM },
        { L_, INF_P,  INF_P,  NORMAL, INF_P,     0 },
        { L_, INF_P,  INF_P,  INF_P,  INF_P,     0 },
        { L_, INF_P,  INF_P,  NaN,    NaN,       0 },

        { L_, INF_P,  NaN,    INF_N,  NaN,       0 },
        { L_, INF_P,  NaN,    NORMAL, NaN,       0 },
        { L_, INF_P,  NaN,    INF_P,  NaN,       0 },
        { L_, INF_P,  NaN,    NaN,    NaN,       0 },

        { L_, NaN,    INF_N,  INF_N,  NaN,       0 },
        { L_, NaN,    INF_N,  NORMAL, NaN,       0 },
        { L_, NaN,    INF_N,  INF_P,  NaN,       0 },
        { L_, NaN,    INF_N,  NaN,    NaN,       0 },

        { L_, NaN,    NORMAL, INF_N,  NaN,       0 },
        { L_, NaN,    NORMAL, NORMAL, NaN,       0 },
        { L_, NaN,    NORMAL, INF_P,  NaN,       0 },
        { L_, NaN,    NORMAL, NaN,    NaN,       0 },

        { L_, NaN,    INF_P,  INF_N,  NaN,       0 },
        { L_, NaN,    INF_P,  NORMAL, NaN,       0 },
        { L_, NaN,    INF_P,  INF_P,  NaN,       0 },
        { L_, NaN,    INF_P,  NaN,    NaN,       0 },

        { L_, NaN,    NaN,    INF_N,  NaN,       0 },
        { L_, NaN,    NaN,    NORMAL, NaN,       0 },
        { L_, NaN,    NaN,    INF_P,  NaN,       0 },
        { L_, NaN,    NaN,    NaN,    NaN,       0 },

        { L_, ZERO,   INF_P,  NORMAL, NaN,    EDOM },
        { L_, INF_P,  ZERO,   NORMAL, NaN,    EDOM },
        { L_, ZERO,   INF_P,  NaN,    NaN,       0 },
        { L_, INF_P,  ZERO,   NaN,    NaN,       0 },

        { L_, sNAN,   NORMAL, NORMAL, NaN,    EDOM },
        { L_, NORMAL, sNAN,   NORMAL, NaN,    EDOM },
        { L_, NORMAL, NORMAL, sNAN,   NaN,    EDOM },
    };


    const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

    for (int ti = 0; ti < NUM_DATA; ++ti) {
        const int     LINE  = DATA[ti].d_line;
        const DECIMAL X     = DATA[ti].d_x;
        const DECIMAL Y     = DATA[ti].d_y;
        const DECIMAL Z     = DATA[ti].d_z;
        const int     ERRNO = DATA[ti].d_errno;

        errno = 0;
        const DECIMAL EXPECTED = DATA[ti].d_expected;

        DECIMAL RESULT = Util::fma(X, Y, Z);
        LOOP1_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
        LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
    }
}

// ============================================================================
//                              USAGE EXAMPLE
// ----------------------------------------------------------------------------

///Example 2: Adding two Decimal Floating Point Values
///- - - - - - - - - - - - - - - - - - - - - - - - - -
// First, we we define the signature of a function that computes the sum of an
// array of security prices, and returns that sum as a decimal floating point
// value:

    bdldfp::DecimalImpUtil::ValueType64
    totalSecurities(bdldfp::DecimalImpUtil::ValueType64 *prices,
                    int                                  numPrices)
        // Return a Decimal Floating Point number representing the arithmetic
        // total of the values specified by 'prices' and 'numPrices'.
    {

// Then, we create a local variable to hold the intermediate sum, and set it to
// 0:

        bdldfp::DecimalImpUtil::ValueType64 total;
        total = bdldfp::DecimalImpUtil::int32ToDecimal64(0);

// Next, we loop over the array of 'prices' and add each price to the
// intermediate 'total':

        for (int i = 0; i < numPrices; ++i) {
            total = bdldfp::DecimalImpUtil::add(total, prices[i]);
        }

// Now, we return the computed total value of the securities:

        return total;
    }

//=============================================================================
//                      TEST DRIVER NAMESPACE CLASS
//-----------------------------------------------------------------------------

static int                test;
static int             verbose;
static int         veryVerbose;
static int     veryVeryVerbose;
static int veryVeryVeryVerbose;
static bslma::TestAllocator *pa;

struct TestDriver {
    static void testCase31();
    static void testCase30();
    static void testCase29();
    static void testCase28();
    static void testCase27();
    static void testCase26();
    static void testCase25();
    static void testCase24();
    static void testCase23();
    static void testCase22();
    static void testCase21();
    static void testCase20();
    static void testCase19();
    static void testCase18();
    static void testCase17();
    static void testCase16();
    static void testCase15();
    static void testCase14();
    static void testCase13();
    static void testCase12();
    static void testCase11();
    static void testCase10();
    static void testCase9();
    static void testCase8();
    static void testCase7();
    static void testCase6();
    static void testCase5();
    static void testCase4();
    static void testCase3();
    static void testCase2();
    static void testCase1();
};

void TestDriver::testCase31()
{
    // ------------------------------------------------------------------------
    // TESTING USAGE EXAMPLE
    //
    // Concerns:
    //:  1 Usage example compiles
    //
    // Plan:
    //:  1 Copy-and-paste usage example into test driver.
    //:  2 Replace 'assert' with 'ASSERT'.
    //
    // Testing:
    //   USAGE EXAMPLE
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING USAGE EXAMPLE" << endl
                      << "=====================" << endl;

///Usage
///-----
// This section shows the intended use of this component.
//
///Example 1: Constructing a Representation of a Value in Decimal
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// A common requirement for decimal floating point types is to be able to
// create a value from independent "coefficient" and "exponent" values, where
// the resulting decimal has the value 'coefficient * 10 ^ exponent'.  In the
// following example we use such a 'coffecicient' and 'exponent' to create
// 'Decimal32', 'Decimal64', and 'Decimal128' values.
//
// First we define values representing the 'coefficient' and 'exponent' (note
// the result should be the value 42.5):

    int coefficient = 425; // Yet another name for significand
    int exponent    =  -1;

// Then we call 'makeDecimal32', 'makeDecimal64', and 'makeDecimal128' to
// construct a 'Decimal32', 'Decimal64', and 'Decimal128' respectively.

    bdldfp::DecimalImpUtil::ValueType32  d32 =
              bdldfp::DecimalImpUtil::makeDecimalRaw32( coefficient, exponent);
    bdldfp::DecimalImpUtil::ValueType64  d64 =
              bdldfp::DecimalImpUtil::makeDecimalRaw64( coefficient, exponent);
    bdldfp::DecimalImpUtil::ValueType128 d128 =
              bdldfp::DecimalImpUtil::makeDecimalRaw128(coefficient, exponent);
//
    ASSERT(bdldfp::DecimalImpUtil::equal(
                      bdldfp::DecimalImpUtil::binaryToDecimal32( 42.5), d32));
    ASSERT(bdldfp::DecimalImpUtil::equal(
                      bdldfp::DecimalImpUtil::binaryToDecimal64( 42.5), d64));
    ASSERT(bdldfp::DecimalImpUtil::equal(
                      bdldfp::DecimalImpUtil::binaryToDecimal128(42.5), d128));

//
///Example 2: Adding two Decimal Floating Point Values
///- - - - - - - - - - - - - - - - - - - - - - - - - -
// Decimal floating point values are frequently used in arithmetic computations
// where the precise representation of decimal values is of paramount
// importance (for example, financial calculations, as currency is typically
// denominated in base-10 decimal values).  In the following example we
// demonstrate computing the sum of a sequence of security prices, where each
// price is held in a 'DecimalImpUtil::ValueType64' value.
//

// Notice that 'add' is called as a function, and is not an operator overload
// for '+'; this is because the 'bdldfp::DecimalImpUtil' utility is intended to
// be used in the implementation of operator overloads on a more full fledged
// type.
//
// Finally, we call the function with some sample data, and check the result:

    bdldfp::DecimalImpUtil::ValueType64 data[16];
//
    for (int i = 0; i < 16; ++i) {
        data[i] = bdldfp::DecimalImpUtil::int32ToDecimal64(i + 1);
    }
//
    bdldfp::DecimalImpUtil::ValueType64 result;
    result = totalSecurities(data, 16);
//
    bdldfp::DecimalImpUtil::ValueType64 expected;
//
    expected = bdldfp::DecimalImpUtil::int32ToDecimal64(16);
//
    // Totals of values from 1 to 'x' are '(x * x + x) / 2':
//
    expected = bdldfp::DecimalImpUtil::add(
                 bdldfp::DecimalImpUtil::multiply(expected, expected),
                 expected);
    expected = bdldfp::DecimalImpUtil::divide(
                         expected,
                         bdldfp::DecimalImpUtil::int32ToDecimal64(2));
//
    ASSERT(bdldfp::DecimalImpUtil::equal(expected, result));

// Notice that arithmetic is unwieldy and hard to visualize.  This is by
// design, as the DecimalImpUtil and subordinate components are not intended
// for public consumption, or direct use in decimal arithmetic.
}

void TestDriver::testCase30()
{
    // ------------------------------------------------------------------------
    // TESTING SAMEQUANTUM
    //
    // Concerns:
    //: 1 Forwarding to the right routines.
    //
    // Plan:
    //:  1 Using table-driven technique:
    //:
    //:    1 Specify a set of arguments representing distinct decimal type
    //:      values and expected result of 'sameQuantum()' method.
    //:
    //:    2 Exercise 'sameQuantum()' using the arguments from (P-1.1) and
    //:      ensure that the result of execution equals the expected value.
    //
    // Testing:
    //   ValueType32  sameQuantum(ValueType32,  ValueType32);
    //   ValueType64  sameQuantum(ValueType64,  ValueType64);
    //   ValueType128 sameQuantum(ValueType128, ValueType128);
    // ------------------------------------------------------------------------

    if (verbose) bsl::cout << "\nTESTING 'sameQuantum' METHOD"
                           << "\n============================"
                           << bsl::endl;

    if (veryVeryVerbose) { T_ bsl::cout << "ValueType32" << bsl::endl; }
    {
        typedef Util::ValueType32 Obj;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DF(X)

        const Obj NaN   = Util::quietNaN32();
        const Obj INF   = Util::infinity32();
        const Obj DEC_X = DEC(1.234567);
        const Obj DEC_Y = DEC(123456.7);

        struct {
            int  d_line;
            Obj  d_x;
            Obj  d_y;
            bool d_expected;
        } DATA[] = {
        //----------------------------------
        // LINE |  X   | DEC_Y  | EXPECTED
        //----------------------------------
        { L_,    DEC_X,  DEC_X,   true     },
        { L_,    DEC_Y,  DEC_Y,   true     },
        { L_,    DEC_X,  DEC_Y,   false    },
        { L_,    DEC_Y,  DEC_X,   false    },
        { L_,    DEC_X,  INF,     false    },
        { L_,    DEC_X,  NaN,     false    },
        { L_,    INF,    DEC_X,   false    },
        { L_,    NaN,    DEC_X,   false    },
        { L_,    NaN,    INF,     false    },
        { L_,    INF,    NaN,     false    },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int   LINE     = DATA[ti].d_line;
            const Obj&  X        = DATA[ti].d_x;
            const Obj&  Y        = DATA[ti].d_y;
            const bool& EXPECTED = DATA[ti].d_expected;
            const bool  RESULT   = Util::sameQuantum(X, Y);

            LOOP_ASSERT(LINE, RESULT == EXPECTED);
        }
#undef DEC
    }

    if (veryVeryVerbose) { T_ bsl::cout << "ValueType64" << bsl::endl; }
    {
        typedef Util::ValueType64 Obj;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DD(X)
        const Obj NaN   = Util::quietNaN64();
        const Obj INF   = Util::infinity64();
        const Obj DEC_X = DEC(1.2345678);
        const Obj DEC_Y = DEC(1234567.8);

        struct {
            int  d_line;
            Obj  d_x;
            Obj  d_y;
            bool d_expected;
        } DATA[] = {
        //----------------------------------
        // LINE |  X   | DEC_Y  | EXPECTED
        //----------------------------------
        { L_,    DEC_X,  DEC_X,   true     },
        { L_,    DEC_Y,  DEC_Y,   true     },
        { L_,    DEC_X,  DEC_Y,   false    },
        { L_,    DEC_Y,  DEC_X,   false    },
        { L_,    DEC_X,  INF,     false    },
        { L_,    DEC_X,  NaN,     false    },
        { L_,    INF,    DEC_X,   false    },
        { L_,    NaN,    DEC_X,   false    },
        { L_,    NaN,    INF,     false    },
        { L_,    INF,    NaN,     false    },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int   LINE     = DATA[ti].d_line;
            const Obj&  X        = DATA[ti].d_x;
            const Obj&  Y        = DATA[ti].d_y;
            const bool& EXPECTED = DATA[ti].d_expected;
            const bool  RESULT   = Util::sameQuantum(X, Y);

            LOOP_ASSERT(LINE, RESULT == EXPECTED);
        }
#undef DEC
    }

    if (veryVeryVerbose) { T_ bsl::cout << "ValueType128" << bsl::endl; }
    {
        typedef Util::ValueType128 Obj;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DL(X)
        const Obj NaN   = Util::quietNaN128();
        const Obj INF   = Util::infinity128();
        const Obj DEC_X = DEC(1.2345678901234567);
        const Obj DEC_Y = DEC(1234567890123456.7);

        struct {
            int  d_line;
            Obj  d_x;
            Obj  d_y;
            bool d_expected;
        } DATA[] = {
        //----------------------------------
        // LINE |  X   | DEC_Y  | EXPECTED
        //----------------------------------
        { L_,    DEC_X,  DEC_X,   true     },
        { L_,    DEC_Y,  DEC_Y,   true     },
        { L_,    DEC_X,  DEC_Y,   false    },
        { L_,    DEC_Y,  DEC_X,   false    },
        { L_,    DEC_X,  INF,     false    },
        { L_,    DEC_X,  NaN,     false    },
        { L_,    INF,    DEC_X,   false    },
        { L_,    NaN,    DEC_X,   false    },
        { L_,    NaN,    INF,     false    },
        { L_,    INF,    NaN,     false    },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int   LINE     = DATA[ti].d_line;
            const Obj&  X        = DATA[ti].d_x;
            const Obj&  Y        = DATA[ti].d_y;
            const bool& EXPECTED = DATA[ti].d_expected;
            const bool  RESULT   = Util::sameQuantum(X, Y);

            LOOP_ASSERT(LINE, RESULT == EXPECTED);
        }
#undef DEC
    }
}

void TestDriver::testCase29()
{
    // ------------------------------------------------------------------------
    // TESTING QUANTIZE
    //
    // Concerns:
    //: 1 Forwarding to the right routines.
    //
    // Plan:
    //:  1 Using table-driven technique:
    //:
    //:    1 Specify a set of arguments representing distinct decimal type
    //:      values and expected result of 'quantize()' method.
    //:
    //:    2 Exercise 'quantize()' method using the arguments from (P-1.1) and
    //:      ensure that the result of execution equals the expected value.
    //
    // Testing:
    //   ValueType32  quantize(ValueType32,    ValueType32);
    //   ValueType64  quantize(ValueType64,    ValueType64);
    //   ValueType128 quantize(ValueType128,   ValueType128);
    //   ValueType32  quantize(ValueType32,    int);
    //   ValueType64  quantize(ValueType64,    int);
    //   ValueType128 quantize(ValueType128,   int);
    //   int          quantizeEqual(ValueType32  *, ValueType32,  int);
    //   int          quantizeEqual(ValueType64  *, ValueType64,  int);
    //   int          quantizeEqual(ValueType128 *, ValueType128, int);
    // ------------------------------------------------------------------------

    if (verbose) bsl::cout << "\nTESTING 'quantize' METHOD"
                           << "\n========================="
                           << bsl::endl;


    if (veryVeryVerbose) { T_ bsl::cout << "ValueType32" << bsl::endl; }
    {
#define DEC(X) BDLDFP_DECIMALIMPUTIL_DF(X)

        typedef Util::ValueType32 Obj;

        const Obj NAN_P =              Util::quietNaN32();
        const Obj NAN_N = Util::negate(Util::quietNaN32());
        const Obj INF_P =              Util::infinity32();
        const Obj INF_N = Util::negate(Util::infinity32());

        struct {
            int d_line;
            int d_significand;
            int d_exponent;
            int d_quantum;
            Obj d_expected;
            int d_retValue;
        } DATA[] = {
        //---------------------------------------------------------------
        // LINE | SIGNIFICAND | EXP | QUANTUM | EXPECTED      | RETVALUE
        //---------------------------------------------------------------
        //---------------------------------------------------------------
        //                Test data for 'quantize()'
            { L_,    1234567,    0,     -1,     NAN_P,             -1   },
            { L_,    1234567,    0,      0,     DEC(1234567e+0),    0   },
            { L_,    1234567,    0,      1,     DEC( 123457e+1),   -1   },
            { L_,    1234567,    0,      2,     DEC(  12346e+2),   -1   },
            { L_,    1234567,    0,      3,     DEC(   1235e+3),   -1   },
            { L_,    1234567,    0,      4,     DEC(    123e+4),   -1   },
            { L_,    1234567,    0,      5,     DEC(     12e+5),   -1   },
            { L_,    1234567,    0,      6,     DEC(      1e+6),   -1   },
            { L_,    1234567,    0,      7,     DEC(      0e+7),   -1   },
        //---------------------------------------------------------------
        //               Test data for 'quantizeEqual()'
            { L_,    12340,      0,      -3,    NAN_P,             -1   },
            { L_,    12340,      0,      -2,    DEC(1234000e-2),    0   },
            { L_,    12340,      0,      -1,    DEC( 123400e-1),    0   },
            { L_,    12340,      0,       0,    DEC(  12340e-0),    0   },
            { L_,    12340,      0,       1,    DEC(   1234e+1),    0   },
            { L_,    12340,      0,       2,    DEC(    123e+2),   -1   },
            { L_,    12340,      0,       3,    DEC(     12e+3),   -1   },
        //---------------------------------------------------------------
        //                    Test lowest exponent
            { L_,        1,    -94,    -101,    NAN_P,             -1   },
            { L_,        1,    -95,    -101,    DEC(1000000e-101),  0   },
            { L_,        1,    -97,    -101,    DEC(  10000e-101),  0   },
            { L_,        1,    -99,    -101,    DEC(    100e-101),  0   },
            { L_,        1,   -101,    -101,    DEC(      1e-101),  0   },
        //---------------------------------------------------------------
        //                    Test highest exponent
            { L_, 1000000,      90,      90,    DEC(1000000e+90),   0   },
            { L_, 1000000,      88,      90,    DEC(  10000e+90),   0   },
            { L_, 1000000,      86,      90,    DEC(    100e+90),   0   },
            { L_, 1000000,      84,      90,    DEC(      1e+90),   0   },
            { L_, 1000000,      83,      90,    DEC(      0e+90),  -1   },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE        = DATA[ti].d_line;
            const int& SIGNIFICAND = DATA[ti].d_significand;
            const int& EXPONENT    = DATA[ti].d_exponent;
            const int& QUANTUM     = DATA[ti].d_quantum;

            const Obj  V = Util::makeDecimalRaw32(SIGNIFICAND, EXPONENT);
            const Obj  E = Util::makeDecimalRaw32(          1, QUANTUM);

            {  //: o ValueType32 quantize(ValueType32, ValueType32);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(    V, NAN_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, NAN_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(    V, INF_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, INF_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(NAN_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N,     E), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N,     E), NAN_N));
            }

            {  //: o ValueType32 quantize(ValueType32, int);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(NAN_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N, 0), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N, 0), NAN_N));

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXPONENT1 = -101;
                    const int   VALID_EXPONENT2 =   90;
                    const int INVALID_EXPONENT1 = -102;
                    const int INVALID_EXPONENT2 =   91;

                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT1));
                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT2));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT1));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT2));
                }
            }

            {  //: o int quantizeEqual(ValueType32 *, ValueType32, int);

                Obj X(V); Obj *X_P(&X);
                Obj Y(V);

                const int& EXPECTED = DATA[ti].d_retValue;
                      int  RESULT   = Util::quantizeEqual(X_P, Y, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X, V));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X, E));
                }

                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_N, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_N, 0));

                const Obj V_N(Util::negate(V));
                      Obj X_N(V_N), *X_N_P(&X_N);
                const Obj Y_N(V_N);

                RESULT = Util::quantizeEqual(X_N_P, Y_N, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X_N, V_N));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X_N, E));
                }

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXP1 = -101;
                    const int   VALID_EXP2 =   90;
                    const int INVALID_EXP1 = -102;
                    const int INVALID_EXP2 =   91;

                    Obj X; Obj *X_P(&X);

                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP1));
                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP2));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP1));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP2));
                }
            }
        }
#undef DEC
    }

    if (veryVeryVerbose) { T_ bsl::cout << "ValueType64" << bsl::endl; }
    {
#define DEC(X) Util::parse64(X)

        typedef Util::ValueType64 Obj;

        const Obj NAN_P =              Util::quietNaN64();
        const Obj NAN_N = Util::negate(Util::quietNaN64());
        const Obj INF_P =              Util::infinity64();
        const Obj INF_N = Util::negate(Util::infinity64());

        struct {
            int           d_line;
            long long int d_significand;
            int           d_exponent;
            int           d_quantum;
            Obj           d_expected;
            int           d_retValue;
        } DATA[] = {
//---------------------------------------------------------------------------
// LINE |  SIGNIFICAND  | EXP | QUANTUM |         EXPECTED             |  RV
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//                    Test data for 'quantize()'
{ L_, 1234567890123456ll,    0,      -1,    NAN_P,                        -1 },
{ L_, 1234567890123456ll,    0,       0,    DEC("1234567890123456e+0"),    0 },
{ L_, 1234567890123456ll,    0,       1,    DEC( "123456789012346e+1"),   -1 },
{ L_, 1234567890123456ll,    0,       2,    DEC(  "12345678901235e+2"),   -1 },
{ L_, 1234567890123456ll,    0,       3,    DEC(   "1234567890123e+3"),   -1 },
{ L_, 1234567890123456ll,    0,       4,    DEC(    "123456789012e+4"),   -1 },
{ L_, 1234567890123456ll,    0,       5,    DEC(     "12345678901e+5"),   -1 },
{ L_, 1234567890123456ll,    0,       6,    DEC(      "1234567890e+6"),   -1 },
{ L_, 1234567890123456ll,    0,       7,    DEC(       "123456789e+7"),   -1 },
{ L_, 1234567890123456ll,    0,       8,    DEC(        "12345679e+8"),   -1 },
{ L_, 1234567890123456ll,    0,       9,    DEC(         "1234568e+9"),   -1 },
{ L_, 1234567890123456ll,    0,      10,    DEC(          "123457e+10"),  -1 },
{ L_, 1234567890123456ll,    0,      11,    DEC(           "12346e+11"),  -1 },
{ L_, 1234567890123456ll,    0,      12,    DEC(            "1235e+12"),  -1 },
{ L_, 1234567890123456ll,    0,      13,    DEC(             "123e+13"),  -1 },
{ L_, 1234567890123456ll,    0,      14,    DEC(              "12e+14"),  -1 },
{ L_, 1234567890123456ll,    0,      15,    DEC(               "1e+15"),  -1 },
{ L_, 1234567890123456ll,    0,      16,    DEC(               "0e+16"),  -1 },
//---------------------------------------------------------------------------
//                    Test data for 'quantizeEqual()'
{ L_,   12345678901230ll,    0,      -3,    NAN_P,                        -1 },
{ L_,   12345678901230ll,    0,      -2,    DEC("1234567890123000e-2"),    0 },
{ L_,   12345678901230ll,    0,      -1,    DEC( "123456789012300e-1"),    0 },
{ L_,   12345678901230ll,    0,       0,    DEC(  "12345678901230e-0"),    0 },
{ L_,   12345678901230ll,    0,       1,    DEC(   "1234567890123e+1"),    0 },
{ L_,   12345678901230ll,    0,       2,    DEC(    "123456789012e+2"),   -1 },
{ L_,   12345678901230ll,    0,       3,    DEC(     "12345678901e+3"),   -1 },
//---------------------------------------------------------------------------
//                    Test lowest exponent
{ L_,                1ll, -382,    -398,    NAN_P,                        -1 },
{ L_,                1ll, -383,    -398,    DEC("1000000000000000e-398"),  0 },
{ L_,                1ll, -386,    -398,    DEC("   1000000000000e-398"),  0 },
{ L_,                1ll, -389,    -398,    DEC(      "1000000000e-398"),  0 },
{ L_,                1ll, -392,    -398,    DEC(         "1000000e-398"),  0 },
{ L_,                1ll, -395,    -398,    DEC(            "1000e-398"),  0 },
{ L_,                1ll, -398,    -398,    DEC(               "1e-398"),  0 },
//---------------------------------------------------------------------------
//                    Test highest exponent
{ L_, 1000000000000000ll,  369,     369,    DEC("1000000000000000e+369"),  0 },
{ L_, 1000000000000000ll,  366,     369,    DEC("   1000000000000e+369"),  0 },
{ L_, 1000000000000000ll,  363,     369,    DEC("      1000000000e+369"),  0 },
{ L_, 1000000000000000ll,  360,     369,    DEC("         1000000e+369"),  0 },
{ L_, 1000000000000000ll,  357,     369,    DEC("            1000e+369"),  0 },
{ L_, 1000000000000000ll,  354,     369,    DEC("               1e+369"),  0 },
{ L_, 1000000000000000ll,  353,     369,    DEC("               0e+369"), -1 },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int            LINE        = DATA[ti].d_line;
            const long long int& SIGNIFICAND = DATA[ti].d_significand;
            const int&           EXPONENT    = DATA[ti].d_exponent;
            const int&           QUANTUM     = DATA[ti].d_quantum;

            const Obj  V = Util::makeDecimalRaw64(SIGNIFICAND, EXPONENT);
            const Obj  E = Util::makeDecimalRaw64(          1, QUANTUM);

            {  //: o ValueType64 quantize(ValueType64, ValueType64);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(    V, NAN_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, NAN_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(    V, INF_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, INF_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(NAN_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N,     E), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N,     E), NAN_N));
            }

            {  //: o ValueType64 quantize(ValueType64, int);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(NAN_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N, 0), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N, 0), NAN_N));

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXPONENT1 = -398;
                    const int   VALID_EXPONENT2 =  369;
                    const int INVALID_EXPONENT1 = -399;
                    const int INVALID_EXPONENT2 =  370;

                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT1));
                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT2));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT1));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT2));
                }
            }

            {  //: o int quantize(ValueType64 *, ValueType64, int);

                Obj X(V); Obj *X_P(&X);
                Obj Y(V);

                const int& EXPECTED = DATA[ti].d_retValue;
                      int  RESULT   = Util::quantizeEqual(X_P, Y, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X, V));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X, E));
                }

                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_N, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_N, 0));

                const Obj V_N(Util::negate(V));
                      Obj X_N(V_N), *X_N_P(&X_N);
                const Obj Y_N(V_N);

                RESULT = Util::quantizeEqual(X_N_P, Y_N, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X_N, V_N));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X_N, E));
                }

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXP1 = -398;
                    const int   VALID_EXP2 =  369;
                    const int INVALID_EXP1 = -399;
                    const int INVALID_EXP2 =  370;

                    Obj X; Obj *X_P(&X);

                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP1));
                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP2));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP1));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP2));
                }
            }
        }
#undef DEC
    }

    if (veryVeryVerbose) { T_ bsl::cout << "ValueType128" << bsl::endl; }
    {
#define DEC(X) Util::parse128(X)

        typedef Util::ValueType128 Obj;

        const Obj NAN_P =              Util::quietNaN128();
        const Obj NAN_N = Util::negate(Util::quietNaN128());
        const Obj INF_P =              Util::infinity128();
        const Obj INF_N = Util::negate(Util::infinity128());

        const char *D128 = "1234567890123456789012345678901234";
        const char *E128 =   "12345678901234567890123456789010";

        struct {
            int           d_line;
            const char   *d_str;
            int           d_quantum;
            Obj           d_expected;
            int           d_retValue;
        } DATA[] = {
//----------------------------------------------------------------------------
// L  |   STR  | QUANTUM |                 EXPECTED                      | RV
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//                    Test data for 'quantize()'
 { L_,  D128,         0, DEC("1234567890123456789012345678901234e+0"),     0 },
 { L_,  D128,         5, DEC(     "12345678901234567890123456789e+5"),    -1 },
 { L_,  D128,        10, DEC(          "123456789012345678901235e+10"),   -1 },
 { L_,  D128,        15, DEC(               "1234567890123456789e+15"),   -1 },
 { L_,  D128,        20, DEC(                    "12345678901235e+20"),   -1 },
 { L_,  D128,        25, DEC(                         "123456789e+25"),   -1 },
 { L_,  D128,        30, DEC(                              "1235e+30"),   -1 },
 { L_,  D128,        33, DEC(                                 "1e+33"),   -1 },
 { L_,  D128,        34, DEC(                                 "0e+34"),   -1 },
//----------------------------------------------------------------------------
//                    Test data for 'quantizeEqual()'
 { L_,  E128,        -3, NAN_P,                                           -1 },
 { L_,  E128,        -2, DEC("1234567890123456789012345678901000e-2"),     0 },
 { L_,  E128,        -1, DEC( "123456789012345678901234567890100e-1"),     0 },
 { L_,  E128,         0, DEC(  "12345678901234567890123456789010e-0"),     0 },
 { L_,  E128,         1, DEC(   "1234567890123456789012345678901e+1"),     0 },
 { L_,  E128,         2, DEC(    "123456789012345678901234567890e+2"),    -1 },
 { L_,  E128,         3, DEC(     "12345678901234567890123456789e+3"),    -1 },
//----------------------------------------------------------------------------
//                    Test lowest exponent
 { L_, "1e-6142", -6176, NAN_P,                                           -1 },
 { L_, "1e-6143", -6176, DEC("1000000000000000000000000000000000e-6176"),  0 },
 { L_, "1e-6148", -6176, DEC(     "10000000000000000000000000000e-6176"),  0 },
 { L_, "1e-6153", -6176, DEC(          "100000000000000000000000e-6176"),  0 },
 { L_, "1e-6158", -6176, DEC(               "1000000000000000000e-6176"),  0 },
 { L_, "1e-6163", -6176, DEC(                    "10000000000000e-6176"),  0 },
 { L_, "1e-6168", -6176, DEC(                         "100000000e-6176"),  0 },
 { L_, "1e-6173", -6176, DEC(                              "1000e-6176"),  0 },
 { L_, "1e-6176", -6176, DEC(                                 "1e-6176"),  0 },
//----------------------------------------------------------------------------
//                    Test highest exponent
 { L_, "1e+6144",  6111, DEC("1000000000000000000000000000000000e+6111"),  0 },
 { L_, "1e+6139",  6111, DEC(     "10000000000000000000000000000e+6111"),  0 },
 { L_, "1e+6134",  6111, DEC(          "100000000000000000000000e+6111"),  0 },
 { L_, "1e+6129",  6111, DEC(               "1000000000000000000e+6111"),  0 },
 { L_, "1e+6124",  6111, DEC(                    "10000000000000e+6111"),  0 },
 { L_, "1e+6119",  6111, DEC(                         "100000000e+6111"),  0 },
 { L_, "1e+6114",  6111, DEC(                              "1000e+6111"),  0 },
 { L_, "1e+6111",  6111, DEC(                                 "1e+6111"),  0 },
 { L_, "1e+6110",  6111, DEC(                                 "0e+6111"), -1 },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int            LINE    = DATA[ti].d_line;
            const char          *STR     = DATA[ti].d_str;
            const int&           QUANTUM = DATA[ti].d_quantum;

            const Obj  V = Util::parse128(STR);
            const Obj  E = Util::makeDecimalRaw128(1, QUANTUM);

            {  //: o ValueType128 quantize(ValueType128, ValueType128);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, E);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(    V, NAN_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, NAN_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(    V, INF_P), NAN_P));
                ASSERT(nanEqual(Util::quantize(    V, INF_N), NAN_N));
                ASSERT(nanEqual(Util::quantize(NAN_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N,     E), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P,     E), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N,     E), NAN_N));
            }

            {  //: o ValueType128 quantize(ValueType128, int);

                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::quantize(V, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                if (!isNaN(EXPECTED)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT, E));
                }

                const Obj V_N        = Util::negate(V);
                const Obj EXPECTED_N = Util::negate(EXPECTED);
                const Obj RESULT_N   = Util::quantize(V_N, QUANTUM);

                LOOP_ASSERT(LINE, nanEqual(RESULT_N, EXPECTED_N));
                if (!isNaN(EXPECTED_N)) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(RESULT_N, E));
                }

                ASSERT(nanEqual(Util::quantize(NAN_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(NAN_N, 0), NAN_N));
                ASSERT(nanEqual(Util::quantize(INF_P, 0), NAN_P));
                ASSERT(nanEqual(Util::quantize(INF_N, 0), NAN_N));

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXPONENT1 = -6176;
                    const int   VALID_EXPONENT2 =  6111;
                    const int INVALID_EXPONENT1 = -6177;
                    const int INVALID_EXPONENT2 =  6112;

                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT1));
                    ASSERT_PASS(Util::quantize(Obj(),   VALID_EXPONENT2));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT1));
                    ASSERT_FAIL(Util::quantize(Obj(), INVALID_EXPONENT2));
                }
            }

            {  //: o int quantize(ValueType128 *, ValueType128, int);

                Obj X(V); Obj *X_P(&X);
                Obj Y(V);

                const int& EXPECTED = DATA[ti].d_retValue;
                      int  RESULT   = Util::quantizeEqual(X_P, Y, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X, V));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X, E));
                }

                const Obj V_N(Util::negate(V));
                      Obj X_N(V_N), *X_N_P(&X_N);
                const Obj Y_N(V_N);

                RESULT = Util::quantizeEqual(X_N_P, Y_N, QUANTUM);

                LOOP_ASSERT(LINE, RESULT == EXPECTED);
                LOOP_ASSERT(LINE, Util::equal(X_N, V_N));
                if (0 == RESULT) {
                    LOOP_ASSERT(LINE, Util::sameQuantum(X_N, E));
                }

                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, NAN_N, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_P, 0));
                ASSERT(-1 == Util::quantizeEqual(X_P, INF_N, 0));

                if (veryVerbose) cout << "\tNegative Testing." << endl;
                {
                    bsls::AssertTestHandlerGuard hG;

                    const int   VALID_EXP1 = -6176;
                    const int   VALID_EXP2 =  6111;
                    const int INVALID_EXP1 = -6177;
                    const int INVALID_EXP2 =  6112;

                    Obj X; Obj *X_P(&X);

                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP1));
                    ASSERT_PASS(Util::quantizeEqual(X_P, X,   VALID_EXP2));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP1));
                    ASSERT_FAIL(Util::quantizeEqual(X_P, X, INVALID_EXP2));
                }
            }
        }
#undef DEC
    }
}

void TestDriver::testCase28()
{
    if (verbose) bsl::cout << "\nTESTING 'fma' METHOD"
                           << "\n===================="
                           << bsl::endl;

    if (veryVeryVerbose) T_ bsl::cout << "ValueType32" << bsl::endl;
    testFma<Util::ValueType32>();

    if (veryVeryVerbose) T_ bsl::cout << "ValueType64" << bsl::endl;
    testFma<Util::ValueType64>();

    if (veryVeryVerbose) T_ bsl::cout << "ValueType128" << bsl::endl;
    testFma<Util::ValueType128>();
}

void TestDriver::testCase27()
{
    // ------------------------------------------------------------------------
    // TESTING MATH FUNCTIONS
    //
    // Concerns:
    //:  1 Since each math function provided by 'IntelDfp' library have been
    //:    thoroughly tested, we only need to make sure that math functions are
    //:    used correctly and that math methods forward arguments to the
    //:    appropriate math implementation function.
    //:
    //: 2 That decimal arguments with higher precision 'ValueType64/128' and
    //:   are not rounded to fit into the decimal numbers with lower precision
    //:   'ValueType32/64' when passed to underlying library's functions.
    //
    // Plan:
    //:  1 Using table-driven technique:
    //:
    //:    1 Specify a set of arguments representing distinct decimal type
    //:      values and expected result of math method execution.
    //:
    //:    2 For functions that accept decimal numbers with higher precision
    //:      select arguments that precision exceeds the lower precision
    //:      decimal types.  C-2.
    //:
    //:    3 Exercise math method using the arguments from (P-1.1-2) and ensure
    //:      that the result of execution equals the expected value.
    //
    // Testing:
    //   ValueType32   copySign  (ValueType32);
    //   ValueType64   copySign  (ValueType64);
    //   ValueType128  copySign  (ValueType128);
    //   ValueType32   exp       (ValueType32);
    //   ValueType64   exp       (ValueType64);
    //   ValueType128  exp       (ValueType128);
    //   ValueType32   log       (ValueType32);
    //   ValueType64   log       (ValueType64);
    //   ValueType128  log       (ValueType128);
    //   ValueType32   logB      (ValueType32);
    //   ValueType64   logB      (ValueType64);
    //   ValueType128  logB      (ValueType128);
    //   ValueType32   log10     (ValueType32);
    //   ValueType64   log10     (ValueType64);
    //   ValueType128  log10     (ValueType128);
    //   ValueType32   fmod      (ValueType32,  ValueType32);
    //   ValueType64   fmod      (ValueType64,  ValueType64);
    //   ValueType128  fmod      (ValueType128, ValueType128);
    //   ValueType32   remainder (ValueType32,  ValueType32);
    //   ValueType64   remainder (ValueType64,  ValueType64);
    //   ValueType128  remainder (ValueType128, ValueType128);
    //   long int      lrint     (ValueType32);
    //   long int      lrint     (ValueType64);
    //   long int      lrint     (ValueType128);
    //   long long int llrint    (ValueType32);
    //   long long int llrint    (ValueType64);
    //   long long int llrint    (ValueType128);
    //   ValueType32   nextafter (ValueType32,  ValueType32);
    //   ValueType64   nextafter (ValueType64,  ValueType64);
    //   ValueType128  nextafter (ValueType128, ValueType128);
    //   ValueType32   nexttoward(ValueType32,  ValueType32);
    //   ValueType64   nexttoward(ValueType64,  ValueType64);
    //   ValueType128  nexttoward(ValueType128, ValueType128);
    //   ValueType32   pow       (ValueType32);
    //   ValueType64   pow       (ValueType64);
    //   ValueType128  pow       (ValueType128);
    //   long int      lround    (ValueType32);
    //   long int      lround    (ValueType64);
    //   long int      lround    (ValueType128);
    //   ValueType32   sqrt      (ValueType32);
    //   ValueType64   sqrt      (ValueType64);
    //   ValueType128  sqrt      (ValueType128);
    //   ValueType32   ceil      (ValueType32);
    //   ValueType64   ceil      (ValueType64);
    //   ValueType128  ceil      (ValueType128);
    //   ValueType32   floor     (ValueType32);
    //   ValueType64   floor     (ValueType64);
    //   ValueType128  floor     (ValueType128);
    //   ValueType32   trunc     (ValueType32);
    //   ValueType64   trunc     (ValueType64);
    //   ValueType128  trunc     (ValueType128);
    //   ValueType32   round     (ValueType32);
    //   ValueType64   round     (ValueType64);
    //   ValueType128  round     (ValueType128);
    //   ValueType32   fabs      (ValueType32);
    //   ValueType64   fabs      (ValueType64);
    //   ValueType128  fabs      (ValueType128);
    // ------------------------------------------------------------------------
    if (verbose) bsl::cout << "\nTESTING MATH METHODS"
                           << "\n===================="
                           << bsl::endl;

    if (veryVerbose) { T_ bsl::cout << "ValueType32" << bsl::endl; }
    {
        typedef Util::ValueType32 Obj;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DF(X)

        const Obj DECIMAL = DEC(1234567.0);
        const Obj NAN_P   = Util::quietNaN32();
        const Obj NAN_N   = Util::negate(NAN_P);
        const Obj sNAN_P  = Util::signalingNaN32();
        const Obj INF_P   = Util::infinity32();
        const Obj INF_N   = Util::negate(INF_P);
        const Obj ZERO_P  = DEC(0.0);
        const Obj ZERO_N  = Util::negate(ZERO_P);
        const Obj MAX_P   = Util::max32();
        const Obj MAX_N   = Util::negate(MAX_P);

        if (veryVerbose) { T_ T_ bsl::cout << "copySign()" << bsl::endl; };
        {
            const Obj DEC_P  = DEC(+1234567.0);
            const Obj DEC_N  = DEC(-1234567.0);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
            } DATA[] = {
            //---------------------------------
            // LINE |  X    |    Y   | EXPECTED
            //---------------------------------
                { L_, DEC_P,   DEC_P,  DEC_P },
                { L_, DEC_P,   DEC_N,  DEC_N },
                { L_, DEC_P,   NAN_P,  DEC_P },
                { L_, DEC_P,   NAN_N,  DEC_N },
                { L_, DEC_P,   INF_P,  DEC_P },
                { L_, DEC_P,   INF_N,  DEC_N },
                { L_, DEC_P,   ZERO_P, DEC_P },
                { L_, DEC_P,   ZERO_N, DEC_N },

                { L_, DEC_N,   DEC_P,  DEC_P },
                { L_, DEC_N,   DEC_N,  DEC_N },
                { L_, DEC_N,   NAN_P,  DEC_P },
                { L_, DEC_N,   NAN_N,  DEC_N },
                { L_, DEC_N,   INF_P,  DEC_P },
                { L_, DEC_N,   INF_N,  DEC_N },
                { L_, DEC_N,   ZERO_P, DEC_P },
                { L_, DEC_N,   ZERO_N, DEC_N },

                { L_, NAN_P,   DEC_P,  NAN_P },
                { L_, NAN_P,   DEC_N,  NAN_N },
                { L_, NAN_P,   NAN_P,  NAN_P },
                { L_, NAN_P,   NAN_N,  NAN_N },
                { L_, NAN_P,   INF_P,  NAN_P },
                { L_, NAN_P,   INF_N,  NAN_N },
                { L_, NAN_P,   ZERO_P, NAN_P },
                { L_, NAN_P,   ZERO_N, NAN_N },

                { L_, NAN_N,   DEC_P,  NAN_P },
                { L_, NAN_N,   DEC_N,  NAN_N },
                { L_, NAN_N,   NAN_P,  NAN_P },
                { L_, NAN_N,   NAN_N,  NAN_N },
                { L_, NAN_N,   INF_P,  NAN_P },
                { L_, NAN_N,   INF_N,  NAN_N },
                { L_, NAN_N,   ZERO_P, NAN_P },
                { L_, NAN_N,   ZERO_N, NAN_N },

                { L_, INF_P,   DEC_P,  INF_P },
                { L_, INF_P,   DEC_N,  INF_N },
                { L_, INF_P,   NAN_P,  INF_P },
                { L_, INF_P,   NAN_N,  INF_N },
                { L_, INF_P,   INF_P,  INF_P },
                { L_, INF_P,   INF_N,  INF_N },
                { L_, INF_P,   ZERO_P, INF_P },
                { L_, INF_P,   ZERO_N, INF_N },

                { L_, INF_N,   DEC_P,  INF_P },
                { L_, INF_N,   DEC_N,  INF_N },
                { L_, INF_N,   NAN_P,  INF_P },
                { L_, INF_N,   NAN_N,  INF_N },
                { L_, INF_N,   INF_P,  INF_P },
                { L_, INF_N,   INF_N,  INF_N },
                { L_, INF_N,   ZERO_P, INF_P },
                { L_, INF_N,   ZERO_N, INF_N },

                { L_, ZERO_P,   DEC_P,  ZERO_P },
                { L_, ZERO_P,   DEC_N,  ZERO_N },
                { L_, ZERO_P,   NAN_P,  ZERO_P },
                { L_, ZERO_P,   NAN_N,  ZERO_N },
                { L_, ZERO_P,   INF_P,  ZERO_P },
                { L_, ZERO_P,   INF_N,  ZERO_N },
                { L_, ZERO_P,   ZERO_P, ZERO_P },
                { L_, ZERO_P,   ZERO_N, ZERO_N },

                { L_, ZERO_N,   DEC_P,  ZERO_P },
                { L_, ZERO_N,   DEC_N,  ZERO_N },
                { L_, ZERO_N,   NAN_P,  ZERO_P },
                { L_, ZERO_N,   NAN_N,  ZERO_N },
                { L_, ZERO_N,   INF_P,  ZERO_P },
                { L_, ZERO_N,   INF_N,  ZERO_N },
                { L_, ZERO_N,   ZERO_P, ZERO_P },
                { L_, ZERO_N,   ZERO_N, ZERO_N },

            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::copySign(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            }
        }

        if (veryVeryVerbose) { T_ T_ bsl::cout << "exp()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //--------------------------------------------------
            // LINE |     X         | EXPECTED        |  ERRNO
            //--------------------------------------------------
                { L_, sNAN_P,         NAN_P,              EDOM },
                { L_, DEC( 12.0),     DEC(1.627548e+5),      0 },
                { L_, DEC(-11.0),     DEC(1.670170e-5),      0 },
                { L_, DEC(9999999.0), INF_P,            ERANGE },
                { L_, NAN_P,          NAN_P,                 0 },
                { L_, NAN_N,          NAN_N,                 0 },
                { L_, INF_P,          INF_P,                 0 },
                { L_, INF_N,          ZERO_P,                0 },
                { L_, ZERO_P,         DEC(1.0),              0 },
                { L_, ZERO_N,         DEC(1.0),              0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);


            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;


                errno = 0;
                const Obj  RESULT = Util::exp(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |     X     | EXPECTED     |  ERRNO
            //-------------------------------------------
                { L_, sNAN_P,     NAN_P,           EDOM },
                { L_, DEC( 12.0), DEC(2.484907),      0 },
                { L_, DEC(-11.0), NAN_P,           EDOM },
                { L_, NAN_P,      NAN_P,              0 },
                { L_, NAN_N,      NAN_N,              0 },
                { L_, INF_P,      INF_P,              0 },
                { L_, INF_N,      NAN_P,           EDOM },
                { L_, ZERO_P,     INF_N,         ERANGE },
                { L_, ZERO_N,     INF_N,         ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::log(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "logB()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------
            // LINE |     X     | EXPECTED |  ERRNO
            //---------------------------------------
                { L_, DEC(  1.0),  ZERO_P,        0 },
                { L_, DEC( 10.0),  DEC(1.0),      0 },
                { L_, DEC( 12.0),  DEC(1.0),      0 },
                { L_, DEC(-11.0),  DEC(1.0),      0 },
                { L_, DEC(-100.0), DEC(2.0),      0 },
                { L_, sNAN_P,      NAN_P,      EDOM },
                { L_, NAN_P,       NAN_P,         0 },
                { L_, NAN_N,       NAN_N,         0 },
                { L_, INF_P,       INF_P,         0 },
                { L_, INF_N,       INF_P,         0 },
                { L_, ZERO_P,      INF_N,    ERANGE },
                { L_, ZERO_N,      INF_N,    ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::logB(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log10()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |     X     | EXPECTED     |  ERRNO
            //-------------------------------------------
                { L_, DEC(  1.0), ZERO_P,             0 },
                { L_, DEC( 12.0), DEC(1.079181),      0 },
                { L_, DEC(-11.0), NAN_P,           EDOM },
                { L_, sNAN_P,     NAN_P,           EDOM },
                { L_, NAN_P,      NAN_P,              0 },
                { L_, NAN_N,      NAN_N,              0 },
                { L_, INF_P,      INF_P,              0 },
                { L_, INF_N,      NAN_P,           EDOM },
                { L_, ZERO_P,     INF_N,         ERANGE },
                { L_, ZERO_N,     INF_N,         ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::log10(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fmod()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //----------------------------------------------
            // LINE |     X    |     Y   | EXPECTED | ERRNO
            //----------------------------------------------
                { L_, DEC( 5.1), DEC(3.0), DEC( 2.1),    0 },
                { L_, DEC(-5.1), DEC(3.0), DEC(-2.1),    0 },
                { L_, DEC( 5.1), NAN_P,    NAN_P,        0 },
                { L_, NAN_P,     DEC(3.0), NAN_P,        0 },
                { L_, NAN_P,     ZERO_P,   NAN_P,        0 },
                { L_, sNAN_P,    DEC(3.0), NAN_P,     EDOM },
                { L_, DEC(1.0),  sNAN_P,   NAN_P,     EDOM },
                { L_, INF_P,     DEC(3.0), NAN_P,     EDOM },
                { L_, INF_N,     DEC(3.0), NAN_P,     EDOM },
                { L_, INF_P,     INF_P,    NAN_P,     EDOM },
                { L_, INF_P,     ZERO_P,   NAN_P,     EDOM },
                { L_, ZERO_P,    ZERO_P,   NAN_P,     EDOM },
                { L_, DEC(5.1),  ZERO_P,   NAN_P,     EDOM },
                { L_, ZERO_P,    DEC(3.0), ZERO_P,       0 },
                { L_, DEC( 5.1), INF_P,    DEC( 5.1),    0 },
                { L_, DEC(-5.1), INF_N,    DEC(-5.1),    0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::fmod(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "remainder()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-----------------------------------------------
            // LINE |     X    |     Y   | EXPECTED  | ERRNO
            //-----------------------------------------------
                { L_, DEC( 7.0), DEC(2.0),  DEC(-1.0),    0 },
                { L_, DEC( 5.1), DEC(3.0),  DEC(-0.9),    0 },
                { L_, DEC(-5.1), DEC(3.0),  DEC( 0.9),    0 },
                { L_, DEC( 5.1), DEC(-3.0), DEC(-0.9),    0 },
                { L_, DEC(-5.1), DEC(-3.0), DEC( 0.9),    0 },
                { L_, DEC( 5.1), NAN_P,     NAN_P,        0 },
                { L_, DEC( 5.1), NAN_N,     NAN_N,        0 },
                { L_, sNAN_P,    DEC(3.0),  NAN_P,     EDOM },
                { L_, DEC(3.0),  sNAN_P,    NAN_P,     EDOM },
                { L_, NAN_P,     DEC(3.0),  NAN_P,        0 },
                { L_, NAN_N,     DEC(3.0),  NAN_N,        0 },
                { L_, INF_P,     DEC(3.0),  NAN_P,     EDOM },
                { L_, INF_N,     ZERO_P,    NAN_P,     EDOM },
                { L_, ZERO_P,    INF_N,     ZERO_P,       0 },
                { L_, DEC( 5.1), INF_P,     DEC( 5.1),    0 },
                { L_, DEC(-5.1), INF_N,     DEC(-5.1),    0 },
                { L_, DEC( 5.1), ZERO_P,    NAN_P,     EDOM },
                { L_, DEC( 5.1), ZERO_N,    NAN_P,     EDOM },
                { L_, ZERO_P,    DEC(3.0),  ZERO_P,       0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::remainder(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lrint()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //-----------------------------------
            // LINE |     X    | EXPECTED | ERRNO
            //-----------------------------------
                { L_, ZERO_P,        0,       0 },
                { L_, ZERO_N,        0,       0 },
                { L_, DEC( 2.3),     2,       0 },
                { L_, DEC( 2.5),     2,       0 },
                { L_, DEC( 3.5),     4,       0 },
                { L_, DEC(-2.3),    -2,       0 },
                { L_, DEC(-2.5),    -2,       0 },
                { L_, DEC(-3.5),    -4,       0 },
                { L_, MAX_P,       NaN,    EDOM },
                { L_, MAX_N,       NaN,    EDOM },
                { L_, sNAN_P,      NaN,    EDOM },
                { L_, NAN_P,       NaN,    EDOM },
                { L_, NAN_N,       NaN,    EDOM },
                { L_, INF_P,       NaN,    EDOM },
                { L_, INF_N,       NaN,    EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long int RESULT = Util::lrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO,    errno,  ERRNO    == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "llrint()" << bsl::endl; }
        {
            const long long int NaN = ~(-1ull >> 1);

            struct {
                int           d_line;
                Obj           d_x;
                long long int d_expected;
                int           d_errno;
            } DATA[] = {
            //-----------------------------------
            // LINE |     X    | EXPECTED | ERRNO
            //-----------------------------------
                { L_, ZERO_P,        0,       0 },
                { L_, ZERO_N,        0,       0 },
                { L_, DEC( 2.3),     2,       0 },
                { L_, DEC( 2.5),     2,       0 },
                { L_, DEC( 3.5),     4,       0 },
                { L_, DEC(-2.3),    -2,       0 },
                { L_, DEC(-2.5),    -2,       0 },
                { L_, DEC(-3.5),    -4,       0 },
                { L_, MAX_P,       NaN,    EDOM },
                { L_, MAX_N,       NaN,    EDOM },
                { L_, sNAN_P,      NaN,    EDOM },
                { L_, NAN_P,       NaN,    EDOM },
                { L_, NAN_N,       NaN,    EDOM },
                { L_, INF_P,       NaN,    EDOM },
                { L_, INF_N,       NaN,    EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int            LINE     = DATA[ti].d_line;
                const Obj&           X        = DATA[ti].d_x;
                const long long int& EXPECTED = DATA[ti].d_expected;
                const int            ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long long int RESULT = Util::llrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO,    errno,  ERRNO    == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nextafter()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_from;
                Obj d_to;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-----------------------------------------------------------
            // LINE |   FROM       |    TO   | EXPECTED        |  ERRNO
            //-----------------------------------------------------------
                { L_, MAX_P,         INF_P,    INF_P,            ERANGE },
                { L_, ZERO_P,        DEC(1.0), DEC(1.0e-101),    ERANGE },
                { L_, DEC(1.0e-101), ZERO_P,   ZERO_P,           ERANGE },
                { L_, DEC(1.0),      DEC(1.0), DEC(1.0),              0 },
                { L_, DEC(1.0),      DEC(2.0), DEC(1.000001),         0 },
                { L_, DEC(1.0),      ZERO_P,   DEC(9.999999e-1),      0 },
                { L_, ZERO_P,        ZERO_P,   ZERO_P,                0 },
                { L_, NAN_P,         NAN_P,    NAN_P,                 0 },
                { L_, NAN_N,         NAN_N,    NAN_N,                 0 },
                { L_, INF_P,         INF_P,    INF_P,                 0 },
                { L_, INF_N,         INF_N,    INF_N,                 0 },
                { L_, INF_P,         INF_N,    MAX_P,                 0 },
                { L_, INF_N,         INF_P,    MAX_N,                 0 },
                { L_, INF_P,         DEC(2.0), MAX_P,                 0 },
                { L_, INF_N,         DEC(2.0), MAX_N,                 0 },
                { L_, sNAN_P,        NAN_P,    NAN_P,              EDOM },
                { L_, DEC(2.0),      sNAN_P,   NAN_P,              EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& FROM     = DATA[ti].d_from;
                const Obj& TO       = DATA[ti].d_to;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::nextafter(FROM, TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nexttoward()" << bsl::endl; }
        {
            struct {
                int                d_line;
                Obj                d_from;
                Util::ValueType128 d_to;
                Obj                d_expected;
                int                d_errno;
            } DATA[] = {
    //------------------------------------------------------------------------
    //LINE | FROM    |          TO            | EXPECTED           |  ERRNO
    //------------------------------------------------------------------------
       { L_, MAX_P,    Util::infinity128(),     INF_P,                ERANGE },
       { L_, ZERO_P,   Util::denormMin128(),    Util::denormMin32(),  ERANGE },
       { L_, DEC(0.0), Util::negate(
                       Util::denormMin128()),   Util::negate(
                                                Util::denormMin32()), ERANGE },
       { L_, NAN_P,    Util::quietNaN128(),     NAN_P,                0      },
       { L_, sNAN_P,   Util::signalingNaN128(), NAN_P,                EDOM   },
       { L_, INF_P,    Util::infinity128(),     INF_P,                0      },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int                 LINE     = DATA[ti].d_line;
                const Obj&                FROM     = DATA[ti].d_from;
                const Util::ValueType128& TO       = DATA[ti].d_to;
                const Obj&                EXPECTED = DATA[ti].d_expected;
                const int                 ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::nexttoward(FROM,TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "pow()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_base;
                Obj d_exponent;
                Obj d_expected;
                int d_errno;
            } DATA[] = {

          //------------------------------------------------------------------
         // LINE |   BASE             |  EXPONENT     | EXPECTED    |  ERRNO
         //-------------------------------------------------------------------
            { L_, ZERO_P,              ZERO_P,         DEC(1.0),           0 },
            { L_, MAX_P,               DEC(2.0),       INF_P,         ERANGE },
            { L_, Util::denormMin32(), DEC(2.0),       ZERO_P,        ERANGE },
            { L_, DEC( 2.0),           DEC(10.0),      DEC(1024.0),        0 },
            { L_, DEC( 2.0),           DEC( 0.5),      DEC(1.414214),      0 },
            { L_, DEC(-2.0),           DEC(-3.0),      DEC(-0.125),        0 },
            { L_, DEC(-1.0),           NAN_P,          NAN_P,              0 },
            { L_, DEC( 1.0),           NAN_P,          DEC(1.0),           0 },
            { L_, INF_P,               DEC( 2.0),      INF_P,              0 },
            { L_, INF_P,               DEC(-1.0),      ZERO_P,             0 },
            { L_, DEC(-1.0),           DEC(0.3333333), NAN_P,           EDOM },
            { L_, ZERO_N,              DEC(-3.0),      INF_N,         ERANGE },
            { L_, NAN_P,               DEC( 2.0),      NAN_P,              0 },
            { L_, sNAN_P,              DEC( 2.0),      NAN_P,           EDOM },
            { L_, DEC(2.0),            sNAN_P,         NAN_P,           EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& BASE     = DATA[ti].d_base;
                const Obj& EXPONENT = DATA[ti].d_exponent;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::pow(BASE, EXPONENT);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lround()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //-----------------------------------
            // LINE |     X    | EXPECTED | ERRNO
            //-----------------------------------
                { L_, DEC( 2.3),  2,          0 },
                { L_, DEC( 2.5),  3,          0 },
                { L_, DEC(-2.3), -2,          0 },
                { L_, DEC(-2.5), -3,          0 },
                { L_, MAX_P,     NaN,      EDOM },
                { L_, MAX_N,     NaN,      EDOM },
                { L_, sNAN_P,    NaN,      EDOM },
                { L_, NAN_P,     NaN,      EDOM },
                { L_, NAN_N,     NaN,      EDOM },
                { L_, INF_P,     NaN,      EDOM },
                { L_, INF_N,     NaN,      EDOM },
                { L_, ZERO_P,     0,          0 },
                { L_, ZERO_N,     0,          0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long int RESULT = Util::lround(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round(x, p)" << bsl::endl; }
        {
            struct {
                int          d_line;
                Obj          d_x;
                unsigned int d_precision;
                Obj          d_expected;
                int          d_errno;
            } DATA[] = {
            //--------------------------------------------------------------
            // LINE |      X          | PRECISION | EXPECTED        | ERRNO
            //--------------------------------------------------------------
            //--------------------------------------------------------------
            //                          Test normal values
            //--------------------------------------------------------------
                { L_, DEC( 1234567e-4),          0, DEC( 123e-0),        0 },
                { L_, DEC( 1234567e-4),          1, DEC( 1235e-1),       0 },
                { L_, DEC( 1234567e-4),          2, DEC( 12346e-2),      0 },
                { L_, DEC( 1234567e-4),          3, DEC( 123457e-3),     0 },
                { L_, DEC( 1234567e-4),          4, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          5, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          6, DEC( 1234567e-4),    0 },

                { L_, DEC(-1234567e-5),          0, DEC(-12e-0),         0 },
                { L_, DEC(-1234567e-5),          1, DEC(-123e-1),        0 },
                { L_, DEC(-1234567e-5),          2, DEC(-1235e-2),       0 },
                { L_, DEC(-1234567e-5),          3, DEC(-12346e-3),      0 },
                { L_, DEC(-1234567e-5),          4, DEC(-123457e-4),     0 },
                { L_, DEC(-1234567e-5),          5, DEC(-1234567e-5),    0 },
                { L_, DEC(-1234567e-5),          6, DEC(-1234567e-5),    0 },

                { L_, DEC( 1234567e-6),          0, DEC( 1e-0),          0 },
                { L_, DEC( 1234567e-6),          1, DEC( 12e-1),         0 },
                { L_, DEC( 1234567e-6),          2, DEC( 123e-2),        0 },
                { L_, DEC( 1234567e-6),          3, DEC( 1235e-3),       0 },
                { L_, DEC( 1234567e-6),          4, DEC( 12346e-4),      0 },
                { L_, DEC( 1234567e-6),          5, DEC( 123457e-5),     0 },
                { L_, DEC( 1234567e-6),          6, DEC( 1234567e-6),    0 },

                { L_, DEC(-1234567e-7),          0, DEC( 0e-0),          0 },
                { L_, DEC(-1234567e-7),          1, DEC(-1e-1),          0 },
                { L_, DEC(-1234567e-7),          2, DEC(-12e-2),         0 },
                { L_, DEC(-1234567e-7),          3, DEC(-123e-3),        0 },
                { L_, DEC(-1234567e-7),          4, DEC(-1235e-4),       0 },
                { L_, DEC(-1234567e-7),          5, DEC(-12346e-5),      0 },
                { L_, DEC(-1234567e-7),          6, DEC(-123457e-6),     0 },

                { L_, DEC( 1234567e-8),          0, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          1, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          2, DEC( 1e-2),          0 },
                { L_, DEC( 1234567e-8),          3, DEC( 12e-3),         0 },
                { L_, DEC( 1234567e-8),          4, DEC( 123e-4),        0 },
                { L_, DEC( 1234567e-8),          5, DEC( 1235e-5),       0 },
                { L_, DEC( 1234567e-8),          6, DEC( 12346e-6),      0 },

                { L_, DEC( 3456000e-5),          0, DEC( 35e-0),         0 },
                { L_, DEC( 3456000e-5),          1, DEC( 346e-1),        0 },
                { L_, DEC( 3456000e-5),          2, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          3, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          4, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          5, DEC( 3456e-2),       0 },

                { L_, DEC(7654321e-101),       102, DEC( 7654321e-101),  0 },
                { L_, DEC(7654321e-101),       101, DEC( 7654321e-101),  0 },
                { L_, DEC(7654321e-101),       100, DEC( 765432e-100),   0 },
                { L_, DEC(7654321e-101),        99, DEC( 76543e-99),     0 },
                { L_, DEC(7654321e-101),        98, DEC( 7654e-98),      0 },
                { L_, DEC(7654321e-101),        97, DEC( 765e-97),       0 },
                { L_, DEC(7654321e-101),        96, DEC( 77e-96),        0 },
                { L_, DEC(7654321e-101),        95, DEC( 8e-95),         0 },
                { L_, DEC(7654321e-101),        94, DEC( 1e-94),         0 },
                { L_, DEC(7654321e-101),        93, DEC( 0e-0),          0 },

                { L_, DEC( 3456e+0),             0, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),             0, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),             0, DEC( 3456e+2),       0 },

                { L_, DEC( 3456e+0),           101, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),           101, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),           101, DEC( 3456e+2),       0 },
            //--------------------------------------------------------------
            //                          Test subnormal values
            //--------------------------------------------------------------
                { L_, DEC(-765432e-101),       102, DEC(-765432e-101),   0 },
                { L_, DEC(-765432e-101),       101, DEC(-765432e-101),   0 },
                { L_, DEC(-765432e-101),       100, DEC(-76543e-100),    0 },
                { L_, DEC(-765432e-101),        99, DEC(-7654e-99),      0 },
                { L_, DEC(-765432e-101),        98, DEC(-765e-98),       0 },
                { L_, DEC(-765432e-101),        97, DEC(-77e-97),        0 },
                { L_, DEC(-765432e-101),        96, DEC(-8e-96),         0 },
                { L_, DEC(-765432e-101),        95, DEC(-1e-95),         0 },
                { L_, DEC(-765432e-101),        94, DEC(0e-0),           0 },

            //--------------------------------------------------------------
            //                          Test special values
            //--------------------------------------------------------------
                { L_, ZERO_P,                    0, ZERO_P,              0 },
                { L_, ZERO_N,                    0, ZERO_N,              0 },
                { L_, INF_P,                     0, INF_P,               0 },
                { L_, INF_N,                     0, INF_N,               0 },
                { L_, NAN_P,                     0, NAN_P,               0 },
                { L_, NAN_N,                     0, NAN_N,               0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int           LINE      = DATA[ti].d_line;
                const Obj&          X         = DATA[ti].d_x;
                const unsigned int& PRECISION = DATA[ti].d_precision;
                const Obj&          EXPECTED  = DATA[ti].d_expected;
                const int           ERRNO     = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::round(X, PRECISION);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round(x, p)" << bsl::endl; }
        {
            struct {
                int          d_line;
                Obj          d_x;
                unsigned int d_precision;
                Obj          d_expected;
                int          d_errno;
            } DATA[] = {
            //--------------------------------------------------------------
            // LINE |      X          | PRECISION | EXPECTED        | ERRNO
            //--------------------------------------------------------------
            //--------------------------------------------------------------
            //                        Test normal values
            //--------------------------------------------------------------
                { L_, DEC( 1234567e-4),          0, DEC( 123e-0),        0 },
                { L_, DEC( 1234567e-4),          1, DEC( 1235e-1),       0 },
                { L_, DEC( 1234567e-4),          2, DEC( 12346e-2),      0 },
                { L_, DEC( 1234567e-4),          3, DEC( 123457e-3),     0 },
                { L_, DEC( 1234567e-4),          4, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          5, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          6, DEC( 1234567e-4),    0 },

                { L_, DEC(-1234567e-5),          0, DEC(-12e-0),         0 },
                { L_, DEC(-1234567e-5),          1, DEC(-123e-1),        0 },
                { L_, DEC(-1234567e-5),          2, DEC(-1235e-2),       0 },
                { L_, DEC(-1234567e-5),          3, DEC(-12346e-3),      0 },
                { L_, DEC(-1234567e-5),          4, DEC(-123457e-4),     0 },
                { L_, DEC(-1234567e-5),          5, DEC(-1234567e-5),    0 },
                { L_, DEC(-1234567e-5),          6, DEC(-1234567e-5),    0 },

                { L_, DEC( 1234567e-6),          0, DEC( 1e-0),          0 },
                { L_, DEC( 1234567e-6),          1, DEC( 12e-1),         0 },
                { L_, DEC( 1234567e-6),          2, DEC( 123e-2),        0 },
                { L_, DEC( 1234567e-6),          3, DEC( 1235e-3),       0 },
                { L_, DEC( 1234567e-6),          4, DEC( 12346e-4),      0 },
                { L_, DEC( 1234567e-6),          5, DEC( 123457e-5),     0 },
                { L_, DEC( 1234567e-6),          6, DEC( 1234567e-6),    0 },

                { L_, DEC(-1234567e-7),          0, DEC( 0e-0),          0 },
                { L_, DEC(-1234567e-7),          1, DEC(-1e-1),          0 },
                { L_, DEC(-1234567e-7),          2, DEC(-12e-2),         0 },
                { L_, DEC(-1234567e-7),          3, DEC(-123e-3),        0 },
                { L_, DEC(-1234567e-7),          4, DEC(-1235e-4),       0 },
                { L_, DEC(-1234567e-7),          5, DEC(-12346e-5),      0 },
                { L_, DEC(-1234567e-7),          6, DEC(-123457e-6),     0 },

                { L_, DEC( 1234567e-8),          0, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          1, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          2, DEC( 1e-2),          0 },
                { L_, DEC( 1234567e-8),          3, DEC( 12e-3),         0 },
                { L_, DEC( 1234567e-8),          4, DEC( 123e-4),        0 },
                { L_, DEC( 1234567e-8),          5, DEC( 1235e-5),       0 },
                { L_, DEC( 1234567e-8),          6, DEC( 12346e-6),      0 },

                { L_, DEC( 3456000e-5),          0, DEC( 35e-0),         0 },
                { L_, DEC( 3456000e-5),          1, DEC( 346e-1),        0 },
                { L_, DEC( 3456000e-5),          2, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          3, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          4, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          5, DEC( 3456e-2),       0 },

                { L_, DEC( 3456e+0),             0, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),             0, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),             0, DEC( 3456e+2),       0 },

                { L_, DEC( 3456e+0),           101, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),           101, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),           101, DEC( 3456e+2),       0 },
            //--------------------------------------------------------------
            //                         Test subnormal values
            //--------------------------------------------------------------
                { L_, DEC(7654321e-101),       102, DEC(7654321e-101),   0 },
                { L_, DEC(7654321e-101),       101, DEC(7654321e-101),   0 },
                { L_, DEC(7654321e-101),       100, DEC(765432e-100),    0 },
                { L_, DEC(7654321e-101),        99, DEC(76543e-99),      0 },
                { L_, DEC(7654321e-101),        98, DEC(7654e-98),       0 },
                { L_, DEC(7654321e-101),        97, DEC(765e-97),        0 },
                { L_, DEC(7654321e-101),        96, DEC(77e-96),         0 },
                { L_, DEC(7654321e-101),        95, DEC(8e-95),          0 },
                { L_, DEC(7654321e-101),        94, DEC(1e-94),          0 },
                { L_, DEC(7654321e-101),        93, DEC(0e-0),           0 },

            //--------------------------------------------------------------
            //                          Test special values
            //--------------------------------------------------------------
                { L_, ZERO_P,                    0, ZERO_P,              0 },
                { L_, ZERO_N,                    0, ZERO_N,              0 },
                { L_, INF_P,                     0, INF_P,               0 },
                { L_, INF_N,                     0, INF_N,               0 },
                { L_, NAN_P,                     0, NAN_P,               0 },
                { L_, NAN_N,                     0, NAN_N,               0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int           LINE      = DATA[ti].d_line;
                const Obj&          X         = DATA[ti].d_x;
                const unsigned int& PRECISION = DATA[ti].d_precision;
                const Obj&          EXPECTED  = DATA[ti].d_expected;
                const int           ERRNO     = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::round(X, PRECISION);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "sqrt()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------
            // LINE |     X     | EXPECTED     | ERRNO
            //------------------------------------------
                { L_, DEC(100.0), DEC(10.0),        0 },
                { L_, DEC(  2.0), DEC(1.414214),    0 },
                { L_, DEC(-1.0),  NAN_P,         EDOM },
                { L_, INF_P,      INF_P,            0 },
                { L_, INF_N,      NAN_P,         EDOM },
                { L_, sNAN_P,     NAN_P,         EDOM },
                { L_, NAN_P,      NAN_P,            0 },
                { L_, NAN_N,      NAN_N,            0 },
                { L_, ZERO_P,     ZERO_P,           0 },
                { L_, ZERO_N,     ZERO_N,           0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::sqrt(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "ceil()" << bsl::endl; }
        {
            const Obj DECIMAL  = DEC(1234567.0);
                  Obj RESULT   = Util::ceil(DEC(0.5));
                  Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::ceil(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::ceil(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::ceil(INF_P),   INF_P));
            ASSERT(Util::equal(Util::ceil(INF_N),   INF_N));
            ASSERT(Util::equal(Util::ceil(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::ceil(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::ceil(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::ceil(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::ceil(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "floor()" << bsl::endl; }
        {
            Obj RESULT   = Util::floor(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::floor(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::floor(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::floor(INF_P),   INF_P));
            ASSERT(Util::equal(Util::floor(INF_N),   INF_N));
            ASSERT(Util::equal(Util::floor(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::floor(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::floor(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::floor(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::floor(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }
        if (veryVerbose) { T_ T_ bsl::cout << "trunc()" << bsl::endl; }
        {
            Obj RESULT   = Util::trunc(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::trunc(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::trunc(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::trunc(INF_P),   INF_P));
            ASSERT(Util::equal(Util::trunc(INF_N),   INF_N));
            ASSERT(Util::equal(Util::trunc(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::trunc(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::trunc(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::trunc(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::trunc(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round()" << bsl::endl; }
        {
            Obj RESULT   = Util::round(DEC(0.5));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::round(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::round(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::round(INF_P),   INF_P));
            ASSERT(Util::equal(Util::round(INF_N),   INF_N));
            ASSERT(Util::equal(Util::round(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::round(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::round(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::round(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::round(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fabs()" << bsl::endl; }
        {
            Obj RESULT   = Util::fabs(DEC(1.0));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::fabs(DEC(-1.0));
            EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::fabs(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::fabs(INF_P),   INF_P));
            ASSERT(Util::equal(Util::fabs(INF_N),   INF_P));
            ASSERT(Util::equal(Util::fabs(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::fabs(ZERO_N),  ZERO_P))
            ASSERT(   nanEqual(Util::fabs(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::fabs(NAN_N),   NAN_P));
            ASSERT(   nanEqual(Util::fabs(sNAN_P),  NAN_P));
        }
#undef DEC
    }

    if (veryVerbose) { T_ bsl::cout << "ValueType64" << bsl::endl; }
    {
        typedef Util::ValueType64 Obj;

#define DEC(X) Util::parse64(#X)

        const Obj DECIMAL = DEC(1234567890123456.0);
        const Obj NAN_P   =              Util::quietNaN64();
        const Obj NAN_N   = Util::negate(Util::quietNaN64());
        const Obj sNAN_P  = Util::signalingNaN64();
        const Obj INF_P   =              Util::infinity64();
        const Obj INF_N   = Util::negate(Util::infinity64());
        const Obj ZERO_P  =              DEC(0.0);
        const Obj ZERO_N  = Util::negate(ZERO_P);
        const Obj MAX_P   =              Util::max64();
        const Obj MAX_N   = Util::negate(MAX_P);

        if (veryVerbose) { T_ T_ bsl::cout << "copySign()" << bsl::endl; }
        {
            const Obj DEC_P  = DEC(+1234567.0);
            const Obj DEC_N  = DEC(-1234567.0);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
            } DATA[] = {
            //---------------------------------
            // LINE |  X    |    Y   | EXPECTED
            //---------------------------------
                { L_, DEC_P,   DEC_P,  DEC_P },
                { L_, DEC_P,   DEC_N,  DEC_N },
                { L_, DEC_P,   NAN_P,  DEC_P },
                { L_, DEC_P,   NAN_N,  DEC_N },
                { L_, DEC_P,   INF_P,  DEC_P },
                { L_, DEC_P,   INF_N,  DEC_N },
                { L_, DEC_P,   ZERO_P, DEC_P },
                { L_, DEC_P,   ZERO_N, DEC_N },

                { L_, DEC_N,   DEC_P,  DEC_P },
                { L_, DEC_N,   DEC_N,  DEC_N },
                { L_, DEC_N,   NAN_P,  DEC_P },
                { L_, DEC_N,   NAN_N,  DEC_N },
                { L_, DEC_N,   INF_P,  DEC_P },
                { L_, DEC_N,   INF_N,  DEC_N },
                { L_, DEC_N,   ZERO_P, DEC_P },
                { L_, DEC_N,   ZERO_N, DEC_N },

                { L_, NAN_P,   DEC_P,  NAN_P },
                { L_, NAN_P,   DEC_N,  NAN_N },
                { L_, NAN_P,   NAN_P,  NAN_P },
                { L_, NAN_P,   NAN_N,  NAN_N },
                { L_, NAN_P,   INF_P,  NAN_P },
                { L_, NAN_P,   INF_N,  NAN_N },
                { L_, NAN_P,   ZERO_P, NAN_P },
                { L_, NAN_P,   ZERO_N, NAN_N },

                { L_, NAN_N,   DEC_P,  NAN_P },
                { L_, NAN_N,   DEC_N,  NAN_N },
                { L_, NAN_N,   NAN_P,  NAN_P },
                { L_, NAN_N,   NAN_N,  NAN_N },
                { L_, NAN_N,   INF_P,  NAN_P },
                { L_, NAN_N,   INF_N,  NAN_N },
                { L_, NAN_N,   ZERO_P, NAN_P },
                { L_, NAN_N,   ZERO_N, NAN_N },

                { L_, INF_P,   DEC_P,  INF_P },
                { L_, INF_P,   DEC_N,  INF_N },
                { L_, INF_P,   NAN_P,  INF_P },
                { L_, INF_P,   NAN_N,  INF_N },
                { L_, INF_P,   INF_P,  INF_P },
                { L_, INF_P,   INF_N,  INF_N },
                { L_, INF_P,   ZERO_P, INF_P },
                { L_, INF_P,   ZERO_N, INF_N },

                { L_, INF_N,   DEC_P,  INF_P },
                { L_, INF_N,   DEC_N,  INF_N },
                { L_, INF_N,   NAN_P,  INF_P },
                { L_, INF_N,   NAN_N,  INF_N },
                { L_, INF_N,   INF_P,  INF_P },
                { L_, INF_N,   INF_N,  INF_N },
                { L_, INF_N,   ZERO_P, INF_P },
                { L_, INF_N,   ZERO_N, INF_N },

                { L_, ZERO_P,   DEC_P,  ZERO_P },
                { L_, ZERO_P,   DEC_N,  ZERO_N },
                { L_, ZERO_P,   NAN_P,  ZERO_P },
                { L_, ZERO_P,   NAN_N,  ZERO_N },
                { L_, ZERO_P,   INF_P,  ZERO_P },
                { L_, ZERO_P,   INF_N,  ZERO_N },
                { L_, ZERO_P,   ZERO_P, ZERO_P },
                { L_, ZERO_P,   ZERO_N, ZERO_N },

                { L_, ZERO_N,   DEC_P,  ZERO_P },
                { L_, ZERO_N,   DEC_N,  ZERO_N },
                { L_, ZERO_N,   NAN_P,  ZERO_P },
                { L_, ZERO_N,   NAN_N,  ZERO_N },
                { L_, ZERO_N,   INF_P,  ZERO_P },
                { L_, ZERO_N,   INF_N,  ZERO_N },
                { L_, ZERO_N,   ZERO_P, ZERO_P },
                { L_, ZERO_N,   ZERO_N, ZERO_N },

            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::copySign(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "exp()" << bsl::endl; }
        {
            const Obj DEC_X1 = DEC( 12.000046);
            const Obj DEC_X2 = DEC(-11.000046);
            const Obj RES_1  = DEC(1.627622783116064e+5);
            const Obj RES_2  = DEC(1.670093252967944e-5);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |     X         | EXPECTED |  ERRNO
            //-------------------------------------------
                { L_, sNAN_P,         NAN_P,       EDOM },
                { L_, DEC_X1,         RES_1,          0 },
                { L_, DEC_X2,         RES_2,          0 },
                { L_, DEC(9999999.0), INF_P,     ERANGE },
                { L_, NAN_P,          NAN_P,          0 },
                { L_, NAN_N,          NAN_N,          0 },
                { L_, INF_P,          INF_P,          0 },
                { L_, INF_N,          ZERO_P,         0 },
                { L_, ZERO_P,         DEC(1.0),       0 },
                { L_, ZERO_N,         DEC(1.0),       0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::exp(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log()" << bsl::endl; }
        {
            const Obj DEC_X = DEC(12.000046);
            const Obj RES_1 = DEC( 2.484910483113986);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------
            // LINE |     X     | EXPECTED |  ERRNO
            //---------------------------------------
                { L_, sNAN_P,     NAN_P,       EDOM },
                { L_, DEC(  1.0), ZERO_P,         0 },
                { L_, DEC_X,      RES_1,          0 },
                { L_, DEC(-11.0), NAN_P,       EDOM },
                { L_, NAN_P,      NAN_P,          0 },
                { L_, NAN_N,      NAN_N,          0 },
                { L_, INF_P,      INF_P,          0 },
                { L_, INF_N,      NAN_P,       EDOM },
                { L_, ZERO_P,     INF_N,     ERANGE },
                { L_, ZERO_N,     INF_N,     ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::log(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "logB()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------------
            // LINE |       X        | EXPECTED |  ERRNO
            //---------------------------------------------
                { L_, DEC(  1.0),      ZERO_P,         0  },
                { L_, DEC( 99.999999), DEC(1.0),       0  },
                { L_, DEC(100.0),      DEC(2.0),       0  },
                { L_, DEC(-11.0),      DEC(1.0),       0  },
                { L_, sNAN_P,          NAN_P,       EDOM  },
                { L_, NAN_P,           NAN_P,          0  },
                { L_, NAN_N,           NAN_N,          0  },
                { L_, INF_P,           INF_P,          0  },
                { L_, INF_N,           INF_P,          0  },
                { L_, ZERO_P,          INF_N,     ERANGE  },
                { L_, ZERO_N,          INF_N,     ERANGE  },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::logB(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log10()" << bsl::endl; }
        {
            const Obj DEC_X = DEC(12.000046);
            const Obj RES_1 = DEC(1.079182910839948);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------
            // LINE |     X     | EXPECTED |  ERRNO
            //---------------------------------------
                { L_, DEC(  1.0), ZERO_P,         0 },
                { L_, DEC_X,      RES_1,          0 },
                { L_, DEC(-11.0), NAN_P,       EDOM },
                { L_, sNAN_P,     NAN_P,       EDOM },
                { L_, NAN_P,      NAN_P,          0 },
                { L_, NAN_N,      NAN_N,          0 },
                { L_, INF_P,      INF_P,          0 },
                { L_, INF_N,      NAN_P,       EDOM },
                { L_, ZERO_P,     INF_N,     ERANGE },
                { L_, ZERO_N,     INF_N,     ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::log10(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fmod()" << bsl::endl; }
        {
            const Obj DEC_X   = DEC( 5.0000002);
            const Obj DEC_Y   = DEC( 3.0000001);
            const Obj DEC_R   = DEC( 2.0000001);
            const Obj DEC_X_N = DEC(-5.0000002);
            const Obj DEC_Y_N = DEC(-3.0000001);
            const Obj DEC_R_N = DEC(-2.0000001);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------
            // LINE |    X   |    Y   | EXPECTED | ERRNO
            //------------------------------------------
                { L_, DEC_X,   DEC_Y,   DEC_R,       0 },
                { L_, DEC_X_N, DEC_Y,   DEC_R_N,     0 },
                { L_, DEC_X,   DEC_Y_N, DEC_R,       0 },
                { L_, DEC_X_N, DEC_Y_N, DEC_R_N,     0 },
                { L_, DEC_X,   NAN_P,   NAN_P,       0 },
                { L_, DEC_X,   NAN_N,   NAN_N,       0 },
                { L_, DEC_X,   INF_P,   DEC_X,       0 },
                { L_, DEC_X,   INF_N,   DEC_X,       0 },
                { L_, DEC_X,   ZERO_P,  NAN_P,    EDOM },
                { L_, DEC_X,   ZERO_N,  NAN_P,    EDOM },
                { L_, sNAN_P,  DEC_X,   NAN_P,    EDOM },
                { L_, DEC_X,   sNAN_P,  NAN_P,    EDOM },
                { L_, NAN_P,   DEC_Y,   NAN_P,       0 },
                { L_, INF_P,   DEC_Y,   NAN_P,    EDOM },
                { L_, ZERO_P,  DEC_Y,   ZERO_P,      0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::fmod(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "remainder()" << bsl::endl; }
        {
            const Obj DEC_X   = DEC( 5.0000003);
            const Obj DEC_Y   = DEC( 3.0000001);
            const Obj DEC_R   = DEC( 0.9999999);
            const Obj DEC_X_N = DEC(-5.0000003);
            const Obj DEC_Y_N = DEC(-3.0000001);
            const Obj DEC_R_N = DEC(-0.9999999);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |    X   |    Y   | EXPECTED | ERRNO
            //-------------------------------------------
                { L_, DEC_X,   DEC_Y,   DEC_R_N,      0 },
                { L_, DEC_X_N, DEC_Y,   DEC_R,        0 },
                { L_, DEC_X,   DEC_Y_N, DEC_R_N,      0 },
                { L_, DEC_X_N, DEC_Y_N, DEC_R,        0 },
                { L_, DEC_X,   NAN_P,   NAN_P,        0 },
                { L_, DEC_X,   NAN_N,   NAN_N,        0 },
                { L_, sNAN_P,  DEC_X,   NAN_P,     EDOM },
                { L_, DEC_X,   sNAN_P,  NAN_P,     EDOM },
                { L_, DEC_X,   INF_P,   DEC_X,        0 },
                { L_, DEC_X_N, INF_N,   DEC_X_N,      0 },
                { L_, DEC_X,   ZERO_P,  NAN_P,     EDOM },
                { L_, DEC_X,   ZERO_N,  NAN_P,     EDOM },
                { L_, NAN_P,   DEC_Y,   NAN_P,        0 },
                { L_, INF_P,   DEC_Y,   NAN_P,     EDOM },
                { L_, ZERO_P,  DEC_Y,   ZERO_P,       0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::remainder(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lrint()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |       X        | EXPECTED | ERRNO
            //-------------------------------------------
                { L_, ZERO_P,            0,          0  },
                { L_, ZERO_N,            0,          0  },
                { L_, DEC( 2.3),         2,          0  },
                { L_, DEC( 2.5),         2,          0  },
                { L_, DEC( 3.5),         4,          0  },
                { L_, DEC(-2.3),        -2,          0  },
                { L_, DEC(-2.5),        -2,          0  },
                { L_, DEC(-3.4999999),  -3,          0  },
                { L_, DEC(-3.5),        -4,          0  },
                { L_, MAX_P,           NaN,       EDOM  },
                { L_, MAX_N,           NaN,       EDOM  },
                { L_, sNAN_P,          NaN,       EDOM  },
                { L_, NAN_P,           NaN,       EDOM  },
                { L_, NAN_N,           NaN,       EDOM  },
                { L_, INF_P,           NaN,       EDOM  },
                { L_, INF_N,           NaN,       EDOM  },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO = DATA[ti].d_errno;

                errno = 0;
                const long int  RESULT   = Util::lrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO,    errno,  ERRNO    == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "llrint()" << bsl::endl; }
        {
            const long long int NaN = ~(-1ull >> 1);

            struct {
                int           d_line;
                Obj           d_x;
                long long int d_expected;
                int           d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |       X        | EXPECTED | ERRNO
            //-------------------------------------------
                { L_, ZERO_P,            0,          0  },
                { L_, ZERO_N,            0,          0  },
                { L_, DEC( 2.3),         2,          0  },
                { L_, DEC( 2.5),         2,          0  },
                { L_, DEC( 3.5),         4,          0  },
                { L_, DEC(-2.3),        -2,          0  },
                { L_, DEC(-2.5),        -2,          0  },
                { L_, DEC(-3.4999999),  -3,          0  },
                { L_, DEC(-3.5),        -4,          0  },
                { L_, MAX_P,           NaN,       EDOM  },
                { L_, MAX_N,           NaN,       EDOM  },
                { L_, sNAN_P,          NaN,       EDOM  },
                { L_, NAN_P,           NaN,       EDOM  },
                { L_, NAN_N,           NaN,       EDOM  },
                { L_, INF_P,           NaN,       EDOM  },
                { L_, INF_N,           NaN,       EDOM  },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int            LINE     = DATA[ti].d_line;
                const Obj&           X        = DATA[ti].d_x;
                const long long int& EXPECTED = DATA[ti].d_expected;
                const int            ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long long int  RESULT   = Util::llrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO,    errno,  ERRNO    == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nextafter()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_from;
                Obj d_to;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------------------------------
            // LINE |   FROM  |     TO   |       EXPECTED          |  ERRNO
            //---------------------------------------------------------------
                { L_, MAX_P,     INF_P,    INF_P,                    ERANGE },
                { L_, DEC(0.0),  DEC(1.0), Util::denormMin64(),      ERANGE },
                { L_, DEC(1.0),  DEC(2.0), DEC(1.000000000000001),        0 },
                { L_, DEC(1.0),  DEC(0.0), DEC(9.999999999999999e-1),     0 },
                { L_, DEC(0.0),  DEC(0.0), DEC(0.0),                      0 },
                { L_, NAN_P,     NAN_P,    NAN_P,                         0 },
                { L_, NAN_N,     NAN_N,    NAN_N,                         0 },
                { L_, INF_P,     INF_P,    INF_P,                         0 },
                { L_, INF_N,     INF_N,    INF_N,                         0 },
                { L_, INF_P,     DEC(2.0), MAX_P,                         0 },
                { L_, INF_N,     DEC(2.0), MAX_N,                         0 },
                { L_, sNAN_P,    NAN_P,    NAN_P,                      EDOM },
                { L_, DEC(2.0),  sNAN_P,   NAN_P,                      EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& FROM     = DATA[ti].d_from;
                const Obj& TO       = DATA[ti].d_to;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::nextafter(FROM, TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nexttoward()" << bsl::endl; }
        {
            struct {
                int                d_line;
                Obj                d_from;
                Util::ValueType128 d_to;
                Obj                d_expected;
                int                d_errno;
            } DATA[] = {
   //-------------------------------------------------------------------------
   // LINE | FROM    |          TO            | EXPECTED           |  ERRNO
   //-------------------------------------------------------------------------
       { L_, MAX_P,    Util::infinity128(),     INF_P,                ERANGE },
       { L_, ZERO_P,   Util::denormMin128(),    Util::denormMin64(),  ERANGE },
       { L_, DEC(0.0), Util::negate(
                       Util::denormMin128()),   Util::negate(
                                                Util::denormMin64()), ERANGE },
       { L_, NAN_P,    Util::quietNaN128(),     NAN_P,                0      },
       { L_, sNAN_P,   Util::signalingNaN128(), NAN_P,                EDOM   },
       { L_, INF_P,    Util::infinity128(),     INF_P,                0      },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int                 LINE     = DATA[ti].d_line;
                const Obj&                FROM     = DATA[ti].d_from;
                const Util::ValueType128& TO       = DATA[ti].d_to;
                const Obj&                EXPECTED = DATA[ti].d_expected;
                const int                 ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::nexttoward(FROM, TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose)  { T_ T_ bsl::cout << "pow()" << bsl::endl; }
        {
            const Obj SQRT_2 = DEC(1.414213562373095);
            const Obj DEC_Y  = DEC(0.333333333333333);

            struct {
                int d_line;
                Obj d_base;
                Obj d_exponent;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //--------------------------------------------------------------
            // LINE |   BASE             |  EXPONENT | EXPECTED   |  ERRNO
            //--------------------------------------------------------------
                { L_, ZERO_P,              ZERO_P,     DEC(1.0),         0 },
                { L_, MAX_P,               DEC(2.0),   INF_P,       ERANGE },
                { L_, Util::denormMin64(), DEC(2.0),   ZERO_P,      ERANGE },
                { L_, DEC( 2.0),           DEC(10.0),  DEC(1024.0),      0 },
                { L_, DEC( 2.0),           DEC( 0.5),  SQRT_2,           0 },
                { L_, DEC(-2.0),           DEC(-3.0),  DEC(-0.125),      0 },
                { L_, DEC(-1.0),           NAN_P,      NAN_P,            0 },
                { L_, DEC( 1.0),           NAN_P,      DEC(1.0),         0 },
                { L_, INF_P,               DEC( 2.0),  INF_P,            0 },
                { L_, INF_P,               DEC(-1.0),  ZERO_P,           0 },
                { L_, DEC(-1.0),           DEC_Y,      NAN_P,         EDOM },
                { L_, ZERO_N,              DEC(-3.0),  INF_N,       ERANGE },
                { L_, NAN_P,               DEC( 2.0),  NAN_P,            0 },
                { L_, sNAN_P,              DEC( 2.0),  NAN_P,         EDOM },
                { L_, DEC(2.0),            sNAN_P,     NAN_P,         EDOM },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& BASE     = DATA[ti].d_base;
                const Obj& EXPONENT = DATA[ti].d_exponent;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::pow(BASE, EXPONENT);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lround()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |     X          | EXPECTED | ERRNO
            //-------------------------------------------
                { L_, DEC( 2.3),           2,         0 },
                { L_, DEC( 2.4999999),     2,         0 },
                { L_, DEC( 2.5),           3,         0 },
                { L_, DEC(-2.3),          -2,         0 },
                { L_, DEC(-2.5),          -3,         0 },
                { L_, MAX_P,              NaN,     EDOM },
                { L_, MAX_N,              NaN,     EDOM },
                { L_, sNAN_P,             NaN,     EDOM },
                { L_, NAN_P,              NaN,     EDOM },
                { L_, NAN_N,              NaN,     EDOM },
                { L_, INF_P,              NaN,     EDOM },
                { L_, INF_N,              NaN,     EDOM },
                { L_, ZERO_P,              0,         0 },
                { L_, ZERO_N,              0,         0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long int RESULT = Util::lround(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round(x, p)" << bsl::endl; }
        {
            struct {
                int          d_line;
                Obj          d_x;
                unsigned int d_precision;
                Obj          d_expected;
                int          d_errno;
            } DATA[] = {
            //--------------------------------------------------------------
            // LINE |      X          | PRECISION | EXPECTED        | ERRNO
            //--------------------------------------------------------------
            //--------------------------------------------------------------
            //                        Test normal values
            //--------------------------------------------------------------
                { L_, DEC( 1234567e-4),          0, DEC( 123e-0),        0 },
                { L_, DEC( 1234567e-4),          1, DEC( 1235e-1),       0 },
                { L_, DEC( 1234567e-4),          2, DEC( 12346e-2),      0 },
                { L_, DEC( 1234567e-4),          3, DEC( 123457e-3),     0 },
                { L_, DEC( 1234567e-4),          4, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          5, DEC( 1234567e-4),    0 },
                { L_, DEC( 1234567e-4),          6, DEC( 1234567e-4),    0 },

                { L_, DEC(-1234567e-5),          0, DEC(-12e-0),         0 },
                { L_, DEC(-1234567e-5),          1, DEC(-123e-1),        0 },
                { L_, DEC(-1234567e-5),          2, DEC(-1235e-2),       0 },
                { L_, DEC(-1234567e-5),          3, DEC(-12346e-3),      0 },
                { L_, DEC(-1234567e-5),          4, DEC(-123457e-4),     0 },
                { L_, DEC(-1234567e-5),          5, DEC(-1234567e-5),    0 },
                { L_, DEC(-1234567e-5),          6, DEC(-1234567e-5),    0 },

                { L_, DEC( 1234567e-6),          0, DEC( 1e-0),          0 },
                { L_, DEC( 1234567e-6),          1, DEC( 12e-1),         0 },
                { L_, DEC( 1234567e-6),          2, DEC( 123e-2),        0 },
                { L_, DEC( 1234567e-6),          3, DEC( 1235e-3),       0 },
                { L_, DEC( 1234567e-6),          4, DEC( 12346e-4),      0 },
                { L_, DEC( 1234567e-6),          5, DEC( 123457e-5),     0 },
                { L_, DEC( 1234567e-6),          6, DEC( 1234567e-6),    0 },

                { L_, DEC(-1234567e-7),          0, DEC( 0e-0),          0 },
                { L_, DEC(-1234567e-7),          1, DEC(-1e-1),          0 },
                { L_, DEC(-1234567e-7),          2, DEC(-12e-2),         0 },
                { L_, DEC(-1234567e-7),          3, DEC(-123e-3),        0 },
                { L_, DEC(-1234567e-7),          4, DEC(-1235e-4),       0 },
                { L_, DEC(-1234567e-7),          5, DEC(-12346e-5),      0 },
                { L_, DEC(-1234567e-7),          6, DEC(-123457e-6),     0 },

                { L_, DEC( 1234567e-8),          0, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          1, DEC( 0e-0),          0 },
                { L_, DEC( 1234567e-8),          2, DEC( 1e-2),          0 },
                { L_, DEC( 1234567e-8),          3, DEC( 12e-3),         0 },
                { L_, DEC( 1234567e-8),          4, DEC( 123e-4),        0 },
                { L_, DEC( 1234567e-8),          5, DEC( 1235e-5),       0 },
                { L_, DEC( 1234567e-8),          6, DEC( 12346e-6),      0 },

                { L_, DEC( 3456000e-5),          0, DEC( 35e-0),         0 },
                { L_, DEC( 3456000e-5),          1, DEC( 346e-1),        0 },
                { L_, DEC( 3456000e-5),          2, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          3, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          4, DEC( 3456e-2),       0 },
                { L_, DEC( 3456000e-5),          5, DEC( 3456e-2),       0 },

                { L_, DEC( 3456e+0),             0, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),             0, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),             0, DEC( 3456e+2),       0 },

                { L_, DEC( 3456e+0),           398, DEC( 3456e+0),       0 },
                { L_, DEC( 3456e+1),           398, DEC( 3456e+1),       0 },
                { L_, DEC( 3456e+2),           398, DEC( 3456e+2),       0 },
            //--------------------------------------------------------------
            //                         Test subnormal values
            //--------------------------------------------------------------
                { L_, DEC(7654321e-398),       399, DEC(7654321e-398),   0 },
                { L_, DEC(7654321e-398),       398, DEC(7654321e-398),   0 },
                { L_, DEC(7654321e-398),       397, DEC(765432e-397),    0 },
                { L_, DEC(7654321e-398),       396, DEC(76543e-396),     0 },
                { L_, DEC(7654321e-398),       395, DEC(7654e-395),      0 },
                { L_, DEC(7654321e-398),       394, DEC(765e-394),       0 },
                { L_, DEC(7654321e-398),       393, DEC(77e-393),        0 },
                { L_, DEC(7654321e-398),       392, DEC(8e-392),         0 },
                { L_, DEC(7654321e-398),       391, DEC(1e-391),         0 },
                { L_, DEC(7654321e-398),       390, DEC(0e-0),           0 },

            //--------------------------------------------------------------
            //                          Test special values
            //--------------------------------------------------------------
                { L_, ZERO_P,                    0, ZERO_P,              0 },
                { L_, ZERO_N,                    0, ZERO_N,              0 },
                { L_, INF_P,                     0, INF_P,               0 },
                { L_, INF_N,                     0, INF_N,               0 },
                { L_, NAN_P,                     0, NAN_P,               0 },
                { L_, NAN_N,                     0, NAN_N,               0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int           LINE      = DATA[ti].d_line;
                const Obj&          X         = DATA[ti].d_x;
                const unsigned int& PRECISION = DATA[ti].d_precision;
                const Obj&          EXPECTED  = DATA[ti].d_expected;
                const int           ERRNO     = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::round(X, PRECISION);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "sqrt()" << bsl::endl; }
        {
            const Obj SQRT_2 = DEC(1.414213562373095);
            const Obj DEC_1  = DEC(8.999999999999996);
            const Obj RES_1  = DEC(2.999999999999999);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------
            // LINE |     X     | EXPECTED | ERRNO
            //------------------------------------------
                { L_, DEC(100.0), DEC(10.0),    0 },
                { L_, DEC_1,      RES_1,        0 },
                { L_, DEC(  2.0), SQRT_2,       0 },
                { L_, DEC(-1.0),  NAN_P,     EDOM },
                { L_, INF_P,      INF_P,        0 },
                { L_, INF_N,      NAN_P,     EDOM },
                { L_, sNAN_P,     NAN_P,     EDOM },
                { L_, NAN_P,      NAN_P,        0 },
                { L_, NAN_N,      NAN_N,        0 },
                { L_, ZERO_P,     ZERO_P,       0 },
                { L_, ZERO_N,     ZERO_N,       0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::sqrt(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "ceil()" << bsl::endl; }
        {
            Obj RESULT   = Util::ceil(DEC(0.5));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::ceil(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::ceil(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::ceil(INF_P),   INF_P));
            ASSERT(Util::equal(Util::ceil(INF_N),   INF_N));
            ASSERT(Util::equal(Util::ceil(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::ceil(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::ceil(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::ceil(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::ceil(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "floor()" << bsl::endl; }
        {
            Obj RESULT   = Util::floor(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::floor(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::floor(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::floor(INF_P),   INF_P));
            ASSERT(Util::equal(Util::floor(INF_N),   INF_N));
            ASSERT(Util::equal(Util::floor(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::floor(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::floor(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::floor(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::floor(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "trunc()" << bsl::endl; }
        {
            Obj RESULT   = Util::trunc(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::trunc(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::trunc(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::trunc(INF_P),   INF_P));
            ASSERT(Util::equal(Util::trunc(INF_N),   INF_N));
            ASSERT(Util::equal(Util::trunc(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::trunc(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::trunc(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::trunc(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::trunc(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round()" << bsl::endl; }
        {
            Obj RESULT   = Util::round(DEC(0.5));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::round(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::round(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::round(INF_P),   INF_P));
            ASSERT(Util::equal(Util::round(INF_N),   INF_N));
            ASSERT(Util::equal(Util::round(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::round(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::round(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::round(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::round(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fabs()" << bsl::endl; }
        {
            Obj RESULT   = Util::fabs(DEC(1.0));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::fabs(DEC(-1.0));
            EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::fabs(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::fabs(INF_P),   INF_P));
            ASSERT(Util::equal(Util::fabs(INF_N),   INF_P));
            ASSERT(Util::equal(Util::fabs(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::fabs(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::fabs(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::fabs(NAN_N),   NAN_P));
        }

#undef DEC
    }

    if (veryVerbose) { T_ bsl::cout << "ValueType128" << bsl::endl; }
    {
        typedef Util::ValueType128 Obj;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DL(X)

        const Obj NAN_P   =              Util::quietNaN128();
        const Obj NAN_N   = Util::negate(Util::quietNaN128());
        const Obj sNAN_P  = Util::signalingNaN128();
        const Obj INF_P   =              Util::infinity128();
        const Obj INF_N   = Util::negate(Util::infinity128());
        const Obj ZERO_P  =              DEC(0.0);
        const Obj ZERO_N  = Util::negate(ZERO_P);
        const Obj MAX_P   =              Util::max128();
        const Obj MAX_N   = Util::negate(MAX_P);

        if (veryVerbose) { T_ T_ bsl::cout << "copySign()" << bsl::endl; }
        {
            const Obj DEC_P  = DEC(+1234567890123456789012345678901234.0);
            const Obj DEC_N  = DEC(-1234567890123456789012345678901234.0);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
            } DATA[] = {
            //---------------------------------
            // LINE |  X    |    Y   | EXPECTED
            //---------------------------------
                { L_, DEC_P,   DEC_P,  DEC_P },
                { L_, DEC_P,   DEC_N,  DEC_N },
                { L_, DEC_P,   NAN_P,  DEC_P },
                { L_, DEC_P,   NAN_N,  DEC_N },
                { L_, DEC_P,   INF_P,  DEC_P },
                { L_, DEC_P,   INF_N,  DEC_N },
                { L_, DEC_P,   ZERO_P, DEC_P },
                { L_, DEC_P,   ZERO_N, DEC_N },

                { L_, DEC_N,   DEC_P,  DEC_P },
                { L_, DEC_N,   DEC_N,  DEC_N },
                { L_, DEC_N,   NAN_P,  DEC_P },
                { L_, DEC_N,   NAN_N,  DEC_N },
                { L_, DEC_N,   INF_P,  DEC_P },
                { L_, DEC_N,   INF_N,  DEC_N },
                { L_, DEC_N,   ZERO_P, DEC_P },
                { L_, DEC_N,   ZERO_N, DEC_N },

                { L_, NAN_P,   DEC_P,  NAN_P },
                { L_, NAN_P,   DEC_N,  NAN_N },
                { L_, NAN_P,   NAN_P,  NAN_P },
                { L_, NAN_P,   NAN_N,  NAN_N },
                { L_, NAN_P,   INF_P,  NAN_P },
                { L_, NAN_P,   INF_N,  NAN_N },
                { L_, NAN_P,   ZERO_P, NAN_P },
                { L_, NAN_P,   ZERO_N, NAN_N },

                { L_, NAN_N,   DEC_P,  NAN_P },
                { L_, NAN_N,   DEC_N,  NAN_N },
                { L_, NAN_N,   NAN_P,  NAN_P },
                { L_, NAN_N,   NAN_N,  NAN_N },
                { L_, NAN_N,   INF_P,  NAN_P },
                { L_, NAN_N,   INF_N,  NAN_N },
                { L_, NAN_N,   ZERO_P, NAN_P },
                { L_, NAN_N,   ZERO_N, NAN_N },

                { L_, INF_P,   DEC_P,  INF_P },
                { L_, INF_P,   DEC_N,  INF_N },
                { L_, INF_P,   NAN_P,  INF_P },
                { L_, INF_P,   NAN_N,  INF_N },
                { L_, INF_P,   INF_P,  INF_P },
                { L_, INF_P,   INF_N,  INF_N },
                { L_, INF_P,   ZERO_P, INF_P },
                { L_, INF_P,   ZERO_N, INF_N },

                { L_, INF_N,   DEC_P,  INF_P },
                { L_, INF_N,   DEC_N,  INF_N },
                { L_, INF_N,   NAN_P,  INF_P },
                { L_, INF_N,   NAN_N,  INF_N },
                { L_, INF_N,   INF_P,  INF_P },
                { L_, INF_N,   INF_N,  INF_N },
                { L_, INF_N,   ZERO_P, INF_P },
                { L_, INF_N,   ZERO_N, INF_N },

                { L_, ZERO_P,   DEC_P,  ZERO_P },
                { L_, ZERO_P,   DEC_N,  ZERO_N },
                { L_, ZERO_P,   NAN_P,  ZERO_P },
                { L_, ZERO_P,   NAN_N,  ZERO_N },
                { L_, ZERO_P,   INF_P,  ZERO_P },
                { L_, ZERO_P,   INF_N,  ZERO_N },
                { L_, ZERO_P,   ZERO_P, ZERO_P },
                { L_, ZERO_P,   ZERO_N, ZERO_N },

                { L_, ZERO_N,   DEC_P,  ZERO_P },
                { L_, ZERO_N,   DEC_N,  ZERO_N },
                { L_, ZERO_N,   NAN_P,  ZERO_P },
                { L_, ZERO_N,   NAN_N,  ZERO_N },
                { L_, ZERO_N,   INF_P,  ZERO_P },
                { L_, ZERO_N,   INF_N,  ZERO_N },
                { L_, ZERO_N,   ZERO_P, ZERO_P },
                { L_, ZERO_N,   ZERO_N, ZERO_N },

            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const Obj  RESULT   = Util::copySign(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "exp()" << bsl::endl; }
        {
            const Obj DEC_X1 = DEC( 12.000000000000046);
            const Obj DEC_X2 = DEC(-11.000000000000046);
            const Obj RES_1  = DEC(1.627547914190114075284104792510385e+5);
            const Obj RES_2  = DEC(1.670170079024489103439916607792290e-5);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |     X         | EXPECTED |  ERRNO
            //-------------------------------------------
                { L_, sNAN_P,         NAN_P,       EDOM },
                { L_, DEC_X1,         RES_1,          0 },
                { L_, DEC_X2,         RES_2,          0 },
                { L_, DEC(9999999.0), INF_P,     ERANGE },
                { L_, NAN_P,          NAN_P,          0 },
                { L_, NAN_N,          NAN_N,          0 },
                { L_, INF_P,          INF_P,          0 },
                { L_, INF_N,          ZERO_P,         0 },
                { L_, ZERO_P,         DEC(1.0),       0 },
                { L_, ZERO_N,         DEC(1.0),       0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::exp(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log()" << bsl::endl; }
        {
            const Obj DEC_X = DEC(12.000000000000046);
            const Obj RES_1 = DEC(2.484906649788004143563042813164865);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------
            // LINE |     X     | EXPECTED |  ERRNO
            //---------------------------------------
                { L_, sNAN_P,     NAN_P,       EDOM },
                { L_, DEC(  1.0), ZERO_P,         0 },
                { L_, DEC_X,      RES_1,          0 },
                { L_, DEC(-11.0), NAN_P,       EDOM },
                { L_, NAN_P,      NAN_P,          0 },
                { L_, NAN_N,      NAN_N,          0 },
                { L_, INF_P,      INF_P,          0 },
                { L_, INF_N,      NAN_P,       EDOM },
                { L_, ZERO_P,     INF_N,     ERANGE },
                { L_, ZERO_N,     INF_N,     ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::log(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "logB()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------------------
            // LINE |       X                  | EXPECTED |  ERRNO
            //------------------------------------------------------
                { L_, DEC(  1.0),                ZERO_P,         0 },
                { L_, DEC( 99.9999999999999999), DEC(1.0),       0 },
                { L_, DEC(100.0),                DEC(2.0),       0 },
                { L_, DEC(-11.0),                DEC(1.0),       0 },
                { L_, sNAN_P,                    NAN_P,       EDOM },
                { L_, NAN_P,                     NAN_P,          0 },
                { L_, NAN_N,                     NAN_N,          0 },
                { L_, INF_P,                     INF_P,          0 },
                { L_, INF_N,                     INF_P,          0 },
                { L_, ZERO_P,                    INF_N,     ERANGE },
                { L_, ZERO_N,                    INF_N,     ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT   = Util::logB(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "log10()" << bsl::endl; }
        {
            const Obj DEC_X = DEC(12.000000000000046);
            const Obj RES_1 = DEC(1.079181246047626492518019655166250);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------
            // LINE |     X     | EXPECTED |  ERRNO
            //---------------------------------------
                { L_, DEC(  1.0), ZERO_P,         0 },
                { L_, DEC_X,      RES_1,          0 },
                { L_, DEC(-11.0), NAN_P,       EDOM },
                { L_, sNAN_P,     NAN_P,       EDOM },
                { L_, NAN_P,      NAN_P,          0 },
                { L_, NAN_N,      NAN_N,          0 },
                { L_, INF_P,      INF_P,          0 },
                { L_, INF_N,      NAN_P,       EDOM },
                { L_, ZERO_P,     INF_N,     ERANGE },
                { L_, ZERO_N,     INF_N,     ERANGE },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::log10(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fmod()" << bsl::endl; }
        {
            const Obj DEC_X   = DEC( 5.0000000000000002);
            const Obj DEC_Y   = DEC( 3.0000000000000001);
            const Obj DEC_R   = DEC( 2.0000000000000001);
            const Obj DEC_X_N = DEC(-5.0000000000000002);
            const Obj DEC_Y_N = DEC(-3.0000000000000001);
            const Obj DEC_R_N = DEC(-2.0000000000000001);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------
            // LINE |    X   |    Y   | EXPECTED | ERRNO
            //------------------------------------------
                { L_, DEC_X,   DEC_Y,   DEC_R,        0 },
                { L_, DEC_X_N, DEC_Y,   DEC_R_N,      0 },
                { L_, DEC_X,   DEC_Y_N, DEC_R,        0 },
                { L_, DEC_X_N, DEC_Y_N, DEC_R_N,      0 },
                { L_, DEC_X,   NAN_P,   NAN_P,        0 },
                { L_, DEC_X,   NAN_N,   NAN_N,        0 },
                { L_, DEC_X,   INF_P,   DEC_X,        0 },
                { L_, DEC_X,   INF_N,   DEC_X,        0 },
                { L_, DEC_X,   ZERO_P,  NAN_P,     EDOM },
                { L_, DEC_X,   ZERO_N,  NAN_P,     EDOM },
                { L_, sNAN_P,  DEC_X,   NAN_P,     EDOM },
                { L_, DEC_X,   sNAN_P,  NAN_P,     EDOM },
                { L_, NAN_P,   DEC_Y,   NAN_P,        0 },
                { L_, INF_P,   DEC_Y,   NAN_P,     EDOM },
                { L_, ZERO_P,  DEC_Y,   ZERO_P,       0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::fmod(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "remainder()" << bsl::endl; }
        {
            const Obj DEC_X   = DEC( 5.0000000000000003);
            const Obj DEC_Y   = DEC( 3.0000000000000001);
            const Obj DEC_R   = DEC( 0.9999999999999999);
            const Obj DEC_X_N = DEC(-5.0000000000000003);
            const Obj DEC_Y_N = DEC(-3.0000000000000001);
            const Obj DEC_R_N = DEC(-0.9999999999999999);

            struct {
                int d_line;
                Obj d_x;
                Obj d_y;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //-------------------------------------------
            // LINE |    X   |    Y   | EXPECTED | ERRNO
            //-------------------------------------------
                { L_, DEC_X,   DEC_Y,   DEC_R_N,      0 },
                { L_, DEC_X_N, DEC_Y,   DEC_R,        0 },
                { L_, DEC_X,   DEC_Y_N, DEC_R_N,      0 },
                { L_, DEC_X_N, DEC_Y_N, DEC_R,        0 },
                { L_, DEC_X,   NAN_P,   NAN_P,        0 },
                { L_, DEC_X,   NAN_N,   NAN_N,        0 },
                { L_, sNAN_P,  DEC_X,   NAN_P,     EDOM },
                { L_, DEC_X,   sNAN_P,  NAN_P,     EDOM },
                { L_, DEC_X,   INF_P,   DEC_X,        0 },
                { L_, DEC_X_N, INF_N,   DEC_X_N,      0 },
                { L_, DEC_X,   ZERO_P,  NAN_P,     EDOM },
                { L_, DEC_X,   ZERO_N,  NAN_P,     EDOM },
                { L_, NAN_P,   DEC_Y,   NAN_P,        0 },
                { L_, INF_P,   DEC_Y,   NAN_P,     EDOM },
                { L_, ZERO_P,  DEC_Y,   ZERO_P,       0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& Y        = DATA[ti].d_y;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::remainder(X, Y);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lrint()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);
            const Obj      DEC_X = DEC(-9223372036854775809.0);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //---------------------------------------------------------------
            // LINE |     X                   | EXPECTED             | ERRNO
            //---------------------------------------------------------------
                { L_, ZERO_P,                    0,                      0  },
                { L_, ZERO_N,                    0,                      0  },
                { L_, DEC_X,                    NaN,                  EDOM  },
                { L_, DEC( 2.3),                 2,                      0  },
                { L_, DEC( 2.5),                 2,                      0  },
                { L_, DEC( 3.5),                 4,                      0  },
                { L_, DEC(-2.3),                -2,                      0  },
                { L_, DEC(-2.5),                -2,                      0  },
                { L_, DEC(-3.4999999999999999), -3,                      0  },
                { L_, DEC(-3.5),                -4,                      0  },
                { L_, MAX_P,                    NaN,                  EDOM  },
                { L_, MAX_N,                    NaN,                  EDOM  },
                { L_, sNAN_P,                   NaN,                  EDOM  },
                { L_, NAN_P,                    NaN,                  EDOM  },
                { L_, NAN_N,                    NaN,                  EDOM  },
                { L_, INF_P,                    NaN,                  EDOM  },
                { L_, INF_N,                    NaN,                  EDOM  },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long int  RESULT   = Util::lrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO, errno,  ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "llrint()" << bsl::endl; }
        {
            const long long int NaN = ~(-1ull >> 1);
            const Obj           DEC_X = DEC(-9223372036854775808.0);

            struct {
                int           d_line;
                Obj           d_x;
                long long int d_expected;
                int           d_errno;
            } DATA[] = {
            //---------------------------------------------------
            // LINE |       X                 | EXPECTED | ERRNO
            //---------------------------------------------------
                { L_, ZERO_P,                    0,           0 },
                { L_, ZERO_N,                    0,           0 },
                { L_, DEC_X,                    NaN,          0 },
                { L_, DEC( 2.3),                 2,           0 },
                { L_, DEC( 2.5),                 2,           0 },
                { L_, DEC( 3.5),                 4,           0 },
                { L_, DEC(-2.3),                -2,           0 },
                { L_, DEC(-2.5),                -2,           0 },
                { L_, DEC(-3.4999999999999999), -3,           0 },
                { L_, DEC(-3.5),                -4,           0 },
                { L_, MAX_P,                    NaN,       EDOM },
                { L_, MAX_N,                    NaN,       EDOM },
                { L_, sNAN_P,                   NaN,       EDOM },
                { L_, NAN_P,                    NaN,       EDOM },
                { L_, NAN_N,                    NaN,       EDOM },
                { L_, INF_P,                    NaN,       EDOM },
                { L_, INF_N,                    NaN,       EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int            LINE     = DATA[ti].d_line;
                const Obj&           X        = DATA[ti].d_x;
                const long long int& EXPECTED = DATA[ti].d_expected;
                const int            ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long long int  RESULT   = Util::llrint(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nextafter()" << bsl::endl; }
        {
            const Obj DEC_1 = DEC( 1.000000000000000000000000000000001);
            const Obj DEC_9 = DEC( 9.999999999999999999999999999999999e-1);

            struct {
                int d_line;
                Obj d_from;
                Obj d_to;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------------------
            // LINE |   FROM  |     TO   |       EXPECTED
            //---------------------------------------------------
                { L_, MAX_P,     INF_P,    INF_P,                ERANGE },
                { L_, DEC(0.0),  DEC(1.0), Util::denormMin128(), ERANGE },
                { L_, DEC(1.0),  DEC(2.0), DEC_1,                     0 },
                { L_, DEC(1.0),  DEC(0.0), DEC_9,                     0 },
                { L_, DEC(0.0),  DEC(0.0), DEC(0.0),                  0 },
                { L_, NAN_P,     NAN_P,    NAN_P,                     0 },
                { L_, NAN_N,     NAN_N,    NAN_N,                     0 },
                { L_, INF_P,     INF_P,    INF_P,                     0 },
                { L_, INF_N,     INF_N,    INF_N,                     0 },
                { L_, INF_P,     DEC(1.0), MAX_P,                     0 },
                { L_, INF_N,     DEC(1.0), MAX_N,                     0 },
                { L_, sNAN_P,    NAN_P,    NAN_P,                  EDOM },
                { L_, DEC(2.0),  sNAN_P,   NAN_P,                  EDOM },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& FROM     = DATA[ti].d_from;
                const Obj& TO       = DATA[ti].d_to;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::nextafter(FROM, TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "nexttoward()" << bsl::endl; }
        {
            struct {
                int d_line;
                Obj d_from;
                Obj d_to;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
  //-------------------------------------------------------------------------
  // LINE | FROM    |          TO          | EXPECTED           |  ERRNO
  //-------------------------------------------------------------------------
      { L_, MAX_P,    INF_P,     INF_P,                 ERANGE },
      { L_, ZERO_P,   Util::denormMin128(),    Util::denormMin128(),  ERANGE },
      { L_, DEC(0.0), Util::negate(
                      Util::denormMin128()),   Util::negate(
                                               Util::denormMin128()), ERANGE },
      { L_, NAN_P,    NAN_P,                   NAN_P,                      0 },
      { L_, sNAN_P,   sNAN_P,                  NAN_P,                   EDOM },
      { L_, INF_P,    INF_P,                   INF_P,                      0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& FROM     = DATA[ti].d_from;
                const Obj& TO       = DATA[ti].d_to;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj RESULT = Util::nexttoward(FROM, TO);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "pow()" << bsl::endl; }
        {
            const Obj SQRT_2 = DEC(1.414213562373095048801688724209698);
            const Obj DEC_Y1 = DEC(2.9999999999999999);
            const Obj DEC_Y2 = DEC(0.3333333333333333);
            const Obj DEC_R1 = DEC(7.999999999999999445482255552043771);

            struct {
                int d_line;
                Obj d_base;
                Obj d_exponent;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //---------------------------------------------------------------
            // LINE |   BASE              |  EXPONENT | EXPECTED   |  ERRNO
            //---------------------------------------------------------------
                { L_, ZERO_P,               ZERO_P,     DEC(1.0),         0 },
                { L_, MAX_P,                DEC(2.0),   INF_P,       ERANGE },
                { L_, Util::denormMin128(), DEC(2.0),   ZERO_P,      ERANGE },
                { L_, DEC( 2.0),            DEC_Y1,     DEC_R1,           0 },
                { L_, DEC( 2.0),            DEC(10.0),  DEC(1024.0),      0 },
                { L_, DEC( 2.0),            DEC( 0.5),  SQRT_2,           0 },
                { L_, DEC(-2.0),            DEC(-3.0),  DEC(-0.125),      0 },
                { L_, DEC(-1.0),            NAN_P,      NAN_P,            0 },
                { L_, DEC( 1.0),            NAN_P,      DEC(1.0),         0 },
                { L_, INF_P,                DEC( 2.0),  INF_P,            0 },
                { L_, INF_P,                DEC(-1.0),  ZERO_P,           0 },
                { L_, DEC(-1.0),            DEC_Y2,     NAN_P,         EDOM },
                { L_, ZERO_N,               DEC(-3.0),  INF_N,       ERANGE },
                { L_, NAN_P,                DEC( 2.0),  NAN_P,            0 },
                { L_, sNAN_P,               DEC( 2.0),  NAN_P,         EDOM },
                { L_, DEC(2.0),             sNAN_P,     NAN_P,         EDOM },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& BASE     = DATA[ti].d_base;
                const Obj& EXPONENT = DATA[ti].d_exponent;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::pow(BASE, EXPONENT);

                LOOP_ASSERT(LINE, nanEqual(EXPECTED, RESULT));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "lround()" << bsl::endl; }
        {
            const long int NaN = ~(-1ul >> 1);
            const Obj      DEC_X = DEC(2.4999999999999999);

            struct {
                int      d_line;
                Obj      d_x;
                long int d_expected;
                int      d_errno;
            } DATA[] = {
            //------------------------------------
            // LINE |    X     | EXPECTED | ERRNO
            //------------------------------------
                { L_, DEC( 2.3),      2,       0 },
                { L_, DEC_X,          2,       0 },
                { L_, DEC( 2.5),      3,       0 },
                { L_, DEC(-2.3),     -2,       0 },
                { L_, DEC(-2.5),     -3,       0 },
                { L_, MAX_P,         NaN,   EDOM },
                { L_, MAX_N,         NaN,   EDOM },
                { L_, sNAN_P,        NaN,   EDOM },
                { L_, NAN_P,         NaN,   EDOM },
                { L_, NAN_N,         NaN,   EDOM },
                { L_, INF_P,         NaN,   EDOM },
                { L_, INF_N,         NaN,   EDOM },
                { L_, ZERO_P,         0,       0 },
                { L_, ZERO_N,         0,       0 },
            };
            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int       LINE     = DATA[ti].d_line;
                const Obj&      X        = DATA[ti].d_x;
                const long int& EXPECTED = DATA[ti].d_expected;
                const int       ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const long int RESULT = Util::lround(X);

                LOOP3_ASSERT(LINE, EXPECTED, RESULT, EXPECTED == RESULT);
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        if (veryVerbose) { T_ T_ bsl::cout << "sqrt()" << bsl::endl; }
        {
            const Obj SQRT_2 = DEC(1.414213562373095048801688724209698);
            const Obj DEC_1  = DEC(8.999999999999999999999999999999996);
            const Obj RES_1  = DEC(2.999999999999999999999999999999999);

            struct {
                int d_line;
                Obj d_x;
                Obj d_expected;
                int d_errno;
            } DATA[] = {
            //------------------------------------------
            // LINE |     X     | EXPECTED | ERRNO
            //------------------------------------------
                { L_, DEC(100.0), DEC(10.0),    0 },
                { L_, DEC_1,      RES_1,        0 },
                { L_, DEC(  2.0), SQRT_2,       0 },
                { L_, DEC(-1.0),  NAN_P,     EDOM },
                { L_, INF_P,      INF_P,        0 },
                { L_, INF_N,      NAN_P,     EDOM },
                { L_, sNAN_P,     NAN_P,     EDOM },
                { L_, NAN_P,      NAN_P,        0 },
                { L_, NAN_N,      NAN_N,        0 },
                { L_, ZERO_P,     ZERO_P,       0 },
                { L_, ZERO_N,     ZERO_N,       0 },
            };

            const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int  LINE     = DATA[ti].d_line;
                const Obj& X        = DATA[ti].d_x;
                const Obj& EXPECTED = DATA[ti].d_expected;
                const int  ERRNO    = DATA[ti].d_errno;

                errno = 0;
                const Obj  RESULT = Util::sqrt(X);

                LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
                LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
            }
        }

        const Obj DECIMAL = DEC(1234567890123456789012345678901234.0);

        if (veryVerbose) { T_ T_ bsl::cout << "ceil()" << bsl::endl; }
        {
            Obj RESULT   = Util::ceil(DEC(0.5));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::ceil(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::ceil(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::ceil(INF_P),   INF_P));
            ASSERT(Util::equal(Util::ceil(INF_N),   INF_N));
            ASSERT(Util::equal(Util::ceil(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::ceil(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::ceil(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::ceil(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::ceil(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "floor()" << bsl::endl; }
        {
            Obj RESULT   = Util::floor(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::floor(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::floor(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::floor(INF_P),   INF_P));
            ASSERT(Util::equal(Util::floor(INF_N),   INF_N));
            ASSERT(Util::equal(Util::floor(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::floor(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::floor(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::floor(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::floor(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "trunc()" << bsl::endl; }
        {
            Obj RESULT   = Util::trunc(DEC(0.5));
            Obj EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::trunc(DEC(-0.5));
            EXPECTED = DEC(0.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::trunc(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::trunc(INF_P),   INF_P));
            ASSERT(Util::equal(Util::trunc(INF_N),   INF_N));
            ASSERT(Util::equal(Util::trunc(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::trunc(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::trunc(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::trunc(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::trunc(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "round()" << bsl::endl; }
        {
            Obj RESULT   = Util::round(DEC(0.5));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::round(DEC(-0.5));
            EXPECTED = DEC(-1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::round(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::round(INF_P),   INF_P));
            ASSERT(Util::equal(Util::round(INF_N),   INF_N));
            ASSERT(Util::equal(Util::round(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::round(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::round(NAN_P),   NAN_P));
            ASSERT(   nanEqual(Util::round(NAN_N),   NAN_N));
            errno = 0;
            ASSERT(   nanEqual(Util::round(sNAN_P),  NAN_P));
            LOOP_ASSERT(L_, EDOM == errno);
        }

        if (veryVerbose) { T_ T_ bsl::cout << "fabs()" << bsl::endl; }
        {
            Obj RESULT   = Util::fabs(DEC(1.0));
            Obj EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            RESULT   = Util::fabs(DEC(-1.0));
            EXPECTED = DEC(1.0);
            ASSERT(Util::equal(RESULT, EXPECTED));

            ASSERT(Util::equal(Util::fabs(DECIMAL), DECIMAL));
            ASSERT(Util::equal(Util::fabs(INF_P),   INF_P));
            ASSERT(Util::equal(Util::fabs(INF_N),   INF_P));
            ASSERT(Util::equal(Util::fabs(ZERO_P),  ZERO_P));
            ASSERT(Util::equal(Util::fabs(ZERO_N),  ZERO_N));
            ASSERT(   nanEqual(Util::fabs(NAN_P),   NAN_P));

            ASSERT(   nanEqual(Util::fabs(NAN_N),   NAN_P));
        }
#undef DEC
    }
}

void TestDriver::testCase26()
{
    // ------------------------------------------------------------------------
    // TESTING 'normalize'
    //
    // Concerns:
    //: 1 The 'normalize' function converts any representations of zero values
    //:   to positive zero value with null significand and exponent.
    //:
    //: 2 The 'normalize' function converts any representations of NaN (either
    //:    signaling or quiet) to quiet NaN.
    //:
    //: 3 The 'normalize' function converts any non-zero values preserving the
    //:   sign.
    //:
    //: 4 The 'normalize' function retains values, that can not be normalized,
    //:   unchanged.
    //
    // Plan:
    //: 1 Use a table-based approach with a) special values, b) boundary
    //:   values,  and c) several hand picked values, to verify that they are
    //:   normalized correctly or remained unchanged.  (C-1..2)
    //:
    //: 2 Separately test 128-bit values, which significands occupy more than
    //:   64 bits.  (C-3..4)
    //
    // Testing:
    //   static ValueType32 normalize(ValueType32 original);
    //   static ValueType64 normalize(ValueType64 original);
    //   static ValueType128 normalize(ValueType128 original);
    // --------------------------------------------------------------------
    if (verbose) bsl::cout << "\nTESTING 'normalize'"
                           << "\n=================="
                           << bsl::endl;

    if (verbose) bsl::cout << "ValueType32" << bsl::endl;
    {
        typedef Util::ValueType32 Type;

        Type SUBN_P  =              Util::denormMin32();
        Type SUBN_N  = Util::negate(Util::denormMin32());
        Type INF_P   =              Util::infinity32();
        Type INF_N   = Util::negate(Util::infinity32());
        Type NAN_Q_P =              Util::quietNaN32();
        Type NAN_Q_N = Util::negate(Util::quietNaN32());
        Type NAN_S_P =              Util::signalingNaN32();
        Type NAN_S_N = Util::negate(Util::signalingNaN32());
        Type MAX_P   =              Util::max32();
        Type MAX_N   = Util::negate(Util::max32());
        Type MIN_P   =              Util::min32();
        Type MIN_N   = Util::negate(Util::min32());

        static const struct {
            int  d_line;      // line
            Type d_original;  // value to normalize
            Type d_expected;  // expected normalized value
        } SPECIAL_DATA[] = {
            // LINE  ORIGINAL   NORMALIZED
            // ----  --------   ----------
            // Test special encoding values
            {  L_,   INF_P,     INF_P     },
            {  L_,   INF_N,     INF_N     },
            {  L_,   SUBN_P,    SUBN_P    },
            {  L_,   SUBN_N,    SUBN_N    },
            {  L_,   NAN_Q_P,   NAN_Q_P   },
            {  L_,   NAN_Q_N,   NAN_Q_N   },
            {  L_,   NAN_S_P,   NAN_Q_P   },
            {  L_,   NAN_S_N,   NAN_Q_N   },

            // Test boundary values
            {  L_,   MIN_P,     MIN_P     },
            {  L_,   MIN_N,     MIN_N     },
            {  L_,   MAX_P,     MAX_P     },
            {  L_,   MAX_N,     MAX_N     },
        };
        enum { NUM_SPECIAL_DATA = sizeof SPECIAL_DATA / sizeof *SPECIAL_DATA };

        for (int ti = 0; ti < NUM_SPECIAL_DATA; ++ti) {
            const int  LINE     = SPECIAL_DATA[ti].d_line;
            const Type ORIGINAL = SPECIAL_DATA[ti].d_original;
            const Type EXPECTED = SPECIAL_DATA[ti].d_expected;

            if (veryVerbose) {
                P(LINE);
            }

            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }

        static const struct {
            int  d_line;             // line
            int  d_origSign;         // sign        of original value
            int  d_origSignificand;  // significand of original value
            int  d_origExponent;     // exponent    of original value
            int  d_expSign;          // sign        of expected value
            int  d_expSignificand;   // significand of expected value
            int  d_expExponent;      // exponent    of expected value
        } ARBITRARY_DATA[] = {
            // LINE O_SIGN O_SIGN-ND O_EXP      E_SIGN E_SIGN-ND E_EXP
            // ---- ------ --------- -----      ------ --------- -----
            // Test zero values
            {  L_,   1,    0,         0  ,       1,    0,         0   },
            {  L_,   1,    0,         1  ,       1,    0,         0   },
            {  L_,  -1,    0,         1  ,       1,    0,         0   },
            {  L_,   1,    0,        -1  ,       1,    0,         0   },
            {  L_,  -1,    0,        -1  ,       1,    0,         0   },
            {  L_,   1,    0,         96 ,       1,    0,         0   },
            {  L_,  -1,    0,         96 ,       1,    0,         0   },
            {  L_,   1,    0,        -101,       1,    0,         0   },
            {  L_,  -1,    0,        -101,       1,    0,         0   },

            // Test arbitrary values
            {  L_,   1,    1    ,     1 ,        1,    1  ,       1   },
            {  L_,  -1,    1    ,     1 ,       -1,    1  ,       1   },
            {  L_,   1,    1    ,    -1 ,        1,    1  ,      -1   },
            {  L_,  -1,    1    ,    -1 ,       -1,    1  ,      -1   },
            {  L_,   1,    12   ,     1 ,        1,    12 ,       1   },
            {  L_,  -1,    12   ,     1 ,       -1,    12 ,       1   },
            {  L_,   1,    12   ,    -1 ,        1,    12 ,      -1   },
            {  L_,  -1,    12   ,    -1 ,       -1,    12 ,      -1   },

            {  L_,   1,    10000,     88,        1,    100 ,      90  },
            {  L_,  -1,    10000,     88,       -1,    100 ,      90  },
            {  L_,   1,    1000 ,     89,        1,    100 ,      90  },
            {  L_,  -1,    1000 ,     89,       -1,    100 ,      90  },
            {  L_,   1,    100  ,     90,        1,    100 ,      90  },
            {  L_,  -1,    100  ,     90,       -1,    100 ,      90  },
            {  L_,   1,    10   ,     91,        1,    100 ,      90  },
            {  L_,  -1,    10   ,     91,       -1,    100 ,      90  },
            {  L_,   1,    100  ,     91,        1,    1000,      90  },
            {  L_,  -1,    100  ,     91,       -1,    1000,      90  },
        };
        enum { NUM_ARBITRARY_DATA =
                              sizeof ARBITRARY_DATA / sizeof *ARBITRARY_DATA };

        for (int ti = 0; ti < NUM_ARBITRARY_DATA; ++ti) {
            const int LINE             = ARBITRARY_DATA[ti].d_line;
            const int ORIG_SIGN        = ARBITRARY_DATA[ti].d_origSign;
            const int ORIG_SIGNIFICAND = ARBITRARY_DATA[ti].d_origSignificand;
            const int ORIG_EXPONENT    = ARBITRARY_DATA[ti].d_origExponent;
            const int EXP_SIGN         = ARBITRARY_DATA[ti].d_expSign;
            const int EXP_SIGNIFICAND  = ARBITRARY_DATA[ti].d_expSignificand;
            const int EXP_EXPONENT     = ARBITRARY_DATA[ti].d_expExponent;

            Type ORIGINAL = Util::scaleB(
                                   Util::makeDecimalRaw32(ORIG_SIGNIFICAND, 0),
                                   ORIG_EXPONENT);
            ORIGINAL = (ORIG_SIGN == -1) ? Util::negate(ORIGINAL) : ORIGINAL;

            Type EXPECTED = Util::scaleB(
                                    Util::makeDecimalRaw32(EXP_SIGNIFICAND, 0),
                                    EXP_EXPONENT);
            EXPECTED = (EXP_SIGN == -1) ? Util::negate(EXPECTED) : EXPECTED;

            if (veryVerbose) {
                P(LINE);
            }
            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }
    }

    if (verbose) bsl::cout << "ValueType64" << bsl::endl;
    {
        typedef Util::ValueType64 Type;

        Type SUBN_P  =              Util::denormMin64();
        Type SUBN_N  = Util::negate(Util::denormMin64());
        Type INF_P   =              Util::infinity64();
        Type INF_N   = Util::negate(Util::infinity64());
        Type NAN_Q_P =              Util::quietNaN64();
        Type NAN_Q_N = Util::negate(Util::quietNaN64());
        Type NAN_S_P =              Util::signalingNaN64();
        Type NAN_S_N = Util::negate(Util::signalingNaN64());
        Type MAX_P   =              Util::max64();
        Type MAX_N   = Util::negate(Util::max64());
        Type MIN_P   =              Util::min64();
        Type MIN_N   = Util::negate(Util::min64());

        static const struct {
            int  d_line;      // line
            Type d_original;  // value to normalize
            Type d_expected;  // expected normalized value
        } S_DATA[] = {
            // LINE  ORIGINAL   NORMALIZED
            // ----  --------   ----------
            // Test special encoding values
            {  L_,   INF_P,     INF_P     },
            {  L_,   INF_N,     INF_N     },
            {  L_,   SUBN_P,    SUBN_P    },
            {  L_,   SUBN_N,    SUBN_N    },
            {  L_,   NAN_Q_P,   NAN_Q_P   },
            {  L_,   NAN_Q_N,   NAN_Q_N   },
            {  L_,   NAN_S_P,   NAN_Q_P   },
            {  L_,   NAN_S_N,   NAN_Q_N   },

            // Test boundary values
            {  L_,   MIN_P,     MIN_P     },
            {  L_,   MIN_N,     MIN_N     },
            {  L_,   MAX_P,     MAX_P     },
            {  L_,   MAX_N,     MAX_N     },
        };
        enum { NUM_S_DATA = sizeof S_DATA / sizeof *S_DATA };

        for (int ti = 0; ti < NUM_S_DATA; ++ti) {
            const int  LINE     = S_DATA[ti].d_line;
            const Type ORIGINAL = S_DATA[ti].d_original;
            const Type EXPECTED = S_DATA[ti].d_expected;

            if (veryVerbose) {
                P(LINE);
            }

            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }

        static const struct {
            int d_line;             // line
            int d_origSign;         // sign        of original value
            int d_origSignificand;  // significand of original value
            int d_origExponent;     // exponent    of original value
            int d_expSign;          // sign        of expected value
            int d_expSignificand;   // significand of expected value
            int d_expExponent;      // exponent    of expected value
        } ARBITRARY_DATA[] = {
            // LINE O_SIGN O_SIGN-ND O_EXP      E_SIGN E_SIGN-ND    E_EXP
            // ---- ------ --------- -----      ------ ---------    -----
            // Test zero values
            {  L_,   1,    0,         0  ,       1,    0,            0   },
            {  L_,   1,    0,         1  ,       1,    0,            0   },
            {  L_,  -1,    0,         1  ,       1,    0,            0   },
            {  L_,   1,    0,        -1  ,       1,    0,            0   },
            {  L_,  -1,    0,        -1  ,       1,    0,            0   },
            {  L_,   1,    0,         384,       1,    0,            0   },
            {  L_,  -1,    0,         384,       1,    0,            0   },
            {  L_,   1,    0,        -383,       1,    0,            0   },
            {  L_,  -1,    0,        -383,       1,    0,            0   },

            // Test arbitrary values
            {  L_,   1,    1    ,     1 ,        1,    1          ,  1   },
            {  L_,  -1,    1    ,     1 ,       -1,    1          ,  1   },
            {  L_,   1,    1    ,    -1 ,        1,    1          , -1   },
            {  L_,  -1,    1    ,    -1 ,       -1,    1          , -1   },
            {  L_,   1,    12   ,     1 ,        1,    12         ,  1   },
            {  L_,  -1,    12   ,     1 ,       -1,    12         ,  1   },
            {  L_,   1,    12   ,    -1 ,        1,    12         , -1   },
            {  L_,  -1,    12   ,    -1 ,       -1,    12         , -1   },

            {  L_,   1,    10000,     367,       1,    100        ,  369 },
            {  L_,  -1,    10000,     367,      -1,    100        ,  369 },
            {  L_,   1,    1000 ,     368,       1,    100        ,  369 },
            {  L_,  -1,    1000 ,     368,      -1,    100        ,  369 },
            {  L_,   1,    100  ,     369,       1,    100        ,  369 },
            {  L_,  -1,    100  ,     369,      -1,    100        ,  369 },
            {  L_,   1,    10   ,     370,       1,    100        ,  369 },
            {  L_,  -1,    10   ,     370,      -1,    100        ,  369 },
            {  L_,   1,    100  ,     370,       1,    1000       ,  369 },
            {  L_,  -1,    100  ,     370,      -1,    1000       ,  369 },
        };
        enum { NUM_ARBITRARY_DATA =
                              sizeof ARBITRARY_DATA / sizeof *ARBITRARY_DATA };

        for (int ti = 0; ti < NUM_ARBITRARY_DATA; ++ti) {
            const int LINE             = ARBITRARY_DATA[ti].d_line;
            const int ORIG_SIGN        = ARBITRARY_DATA[ti].d_origSign;
            const int ORIG_SIGNIFICAND = ARBITRARY_DATA[ti].d_origSignificand;
            const int ORIG_EXPONENT    = ARBITRARY_DATA[ti].d_origExponent;
            const int EXP_SIGN         = ARBITRARY_DATA[ti].d_expSign;
            const int EXP_SIGNIFICAND  = ARBITRARY_DATA[ti].d_expSignificand;
            const int EXP_EXPONENT     = ARBITRARY_DATA[ti].d_expExponent;

            Type ORIGINAL = Util::scaleB(
                                   Util::makeDecimalRaw64(ORIG_SIGNIFICAND, 0),
                                   ORIG_EXPONENT);
            ORIGINAL = (ORIG_SIGN == -1) ? Util::negate(ORIGINAL) : ORIGINAL;

            Type EXPECTED = Util::scaleB(
                                    Util::makeDecimalRaw64(EXP_SIGNIFICAND, 0),
                                    EXP_EXPONENT);
            EXPECTED = (EXP_SIGN == -1) ? Util::negate(EXPECTED) : EXPECTED;

            if (veryVerbose) {
                P(LINE);
            }
            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }
    }

    if (verbose) bsl::cout << "ValueType128" << bsl::endl;
    {
        typedef Util::ValueType128 Type;

        Type SUBN_P  =              Util::denormMin128();
        Type SUBN_N  = Util::negate(Util::denormMin128());
        Type INF_P   =              Util::infinity128();
        Type INF_N   = Util::negate(Util::infinity128());
        Type NAN_Q_P =              Util::quietNaN128();
        Type NAN_Q_N = Util::negate(Util::quietNaN128());
        Type NAN_S_P =              Util::signalingNaN128();
        Type NAN_S_N = Util::negate(Util::signalingNaN128());
        Type MAX_P   =              Util::max128();
        Type MAX_N   = Util::negate(Util::max128());
        Type MIN_P   =              Util::min128();
        Type MIN_N   = Util::negate(Util::min128());

        static const struct {
            int  d_line;      // line
            Type d_original;  // value to normalize
            Type d_expected;  // expected normalized value
        } SPECIAL_DATA[] = {
            // LINE  ORIGINAL   NORMALIZED
            // ----  --------   ----------
            // Test special encoding values
            {  L_,   INF_P,     INF_P     },
            {  L_,   INF_N,     INF_N     },
            {  L_,   SUBN_P,    SUBN_P    },
            {  L_,   SUBN_N,    SUBN_N    },
            {  L_,   NAN_Q_P,   NAN_Q_P   },
            {  L_,   NAN_Q_N,   NAN_Q_N   },
            {  L_,   NAN_S_P,   NAN_Q_P   },
            {  L_,   NAN_S_N,   NAN_Q_N   },

            // Test boundary values
            {  L_,   MIN_P,     MIN_P     },
            {  L_,   MIN_N,     MIN_N     },
            {  L_,   MAX_P,     MAX_P     },
            {  L_,   MAX_N,     MAX_N     },
        };
        enum { NUM_SPECIAL_DATA = sizeof SPECIAL_DATA / sizeof *SPECIAL_DATA };

        for (int ti = 0; ti < NUM_SPECIAL_DATA; ++ti) {
            const int  LINE     = SPECIAL_DATA[ti].d_line;
            const Type ORIGINAL = SPECIAL_DATA[ti].d_original;
            const Type EXPECTED = SPECIAL_DATA[ti].d_expected;

            if (veryVerbose) {
                P(LINE);
            }

            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }

        static const struct {
            int  d_line;             // line
            int  d_origSign;         // sign        of original value
            int  d_origSignificand;  // significand of original value
            int  d_origExponent;     // exponent    of original value
            int  d_expSign;          // sign        of expected value
            int  d_expSignificand;   // significand of expected value
            int  d_expExponent;      // exponent    of expected value
        } ARBITRARY_DATA[] = {
            // LINE O_SIGN O_SIGN-ND O_EXP      E_SIGN E_SIGN-ND E_EXP
            // ---- ------ --------- -----      ------ --------- ------
            // Test zero values
            {  L_,   1,    0,         0   ,      1,    0,         0    },
            {  L_,   1,    0,         1   ,      1,    0,         0    },
            {  L_,  -1,    0,         1   ,      1,    0,         0    },
            {  L_,   1,    0,        -1   ,      1,    0,         0    },
            {  L_,  -1,    0,        -1   ,      1,    0,         0    },
            {  L_,   1,    0,         6144,      1,    0,         0    },
            {  L_,  -1,    0,         6144,      1,    0,         0    },
            {  L_,   1,    0,        -6143,      1,    0,         0    },
            {  L_,  -1,    0,        -6143,      1,    0,         0    },

            // Test arbitrary values
            {  L_,   1,    1    ,     1   ,      1,    1  ,       1    },
            {  L_,  -1,    1    ,     1   ,     -1,    1  ,       1    },
            {  L_,   1,    1    ,    -1   ,      1,    1  ,      -1    },
            {  L_,  -1,    1    ,    -1   ,     -1,    1  ,      -1    },

            {  L_,   1,    10000,     6109,      1,    100 ,      6111 },
            {  L_,  -1,    10000,     6109,     -1,    100 ,      6111 },
            {  L_,   1,    1000 ,     6110,      1,    100 ,      6111 },
            {  L_,  -1,    1000 ,     6110,     -1,    100 ,      6111 },
            {  L_,   1,    100  ,     6111,      1,    100 ,      6111 },
            {  L_,  -1,    100  ,     6111,     -1,    100 ,      6111 },
            {  L_,   1,    10   ,     6112,      1,    100 ,      6111 },
            {  L_,  -1,    10   ,     6112,     -1,    100 ,      6111 },
            {  L_,   1,    100  ,     6112,      1,    1000,      6111 },
            {  L_,  -1,    100  ,     6112,     -1,    1000,      6111 },
        };
        enum { NUM_ARBITRARY_DATA =
                              sizeof ARBITRARY_DATA / sizeof *ARBITRARY_DATA };

        for (int ti = 0; ti < NUM_ARBITRARY_DATA; ++ti) {
            const int LINE             = ARBITRARY_DATA[ti].d_line;
            const int ORIG_SIGN        = ARBITRARY_DATA[ti].d_origSign;
            const int ORIG_SIGNIFICAND = ARBITRARY_DATA[ti].d_origSignificand;
            const int ORIG_EXPONENT    = ARBITRARY_DATA[ti].d_origExponent;
            const int EXP_SIGN         = ARBITRARY_DATA[ti].d_expSign;
            const int EXP_SIGNIFICAND  = ARBITRARY_DATA[ti].d_expSignificand;
            const int EXP_EXPONENT     = ARBITRARY_DATA[ti].d_expExponent;

            Type ORIGINAL = Util::scaleB(
                                  Util::makeDecimalRaw128(ORIG_SIGNIFICAND, 0),
                                  ORIG_EXPONENT);
            ORIGINAL = (ORIG_SIGN == -1) ? Util::negate(ORIGINAL) : ORIGINAL;

            Type EXPECTED = Util::scaleB(
                                   Util::makeDecimalRaw128(EXP_SIGNIFICAND, 0),
                                   EXP_EXPONENT);
            EXPECTED = (EXP_SIGN == -1) ? Util::negate(EXPECTED) : EXPECTED;

            if (veryVerbose) {
                P(LINE);
            }

            Type result = Util::normalize(ORIGINAL);
            ASSERTV(LINE, checkBitsEquality(EXPECTED, result));
        }

        // Testing the 128-bit division.
        {
            const Type ORIGINAL = Util::add(
                               Util::uint64ToDecimal128(0xFFFFFFFFFFFFFFFFull),
                               Util::uint64ToDecimal128( 1));

            const Type     DIV_MULT   =   Util::makeDecimalRaw128(10, 0);
                // multiplier divisible by powers of 10

            const Type NON_DIV_MULT[] = {
                                             Util::makeDecimalRaw128(11, 0),
                                             Util::makeDecimalRaw128(222, 0),
                                             Util::makeDecimalRaw128(3333, 0),
                                             Util::makeDecimalRaw128(44444, 0),
                                             Util::makeDecimalRaw128(666666, 0)
                                        };

            Type normalized = Util::normalize(ORIGINAL);
            ASSERTV(Util::equal(      normalized, ORIGINAL));
            ASSERTV(checkBitsEquality(normalized, ORIGINAL));

            Type divValue   = ORIGINAL;
            for (int i = 0; i < 5; ++i) {
                divValue   = Util::multiply(divValue, DIV_MULT);
                normalized = Util::normalize(divValue);
                ASSERTV( Util::equal(      normalized, divValue));
                ASSERTV(!checkBitsEquality(normalized, divValue));
            }

            for (int i = 0; i < 5; ++i) {
                Type nonDivValue = Util::multiply(ORIGINAL, NON_DIV_MULT[i]);
                normalized       = Util::normalize(nonDivValue);
                ASSERTV(i, Util::equal(      normalized, nonDivValue));
                ASSERTV(i, checkBitsEquality(normalized, nonDivValue));
            }
        }
    }
}

void TestDriver::testCase25()
{
    // ------------------------------------------------------------------------
    // TESTING 'classify'
    //
    // Concerns:
    //: 1 The 'classify' function correctly determines type of any Decimal
    //:   object.
    //
    // Plan:
    //: 1 Use 'classify' to determine class of Decimal objects having different
    //:   valid values including minimum and maximum values and special values
    //:   such as 'NaN' and 'Inf'.  Verify returned results.  (C-1)
    //
    // Testing:
    //   static int classify(ValueType32  x);
    //   static int classify(ValueType64  x);
    //   static int classify(ValueType128 x);
    // --------------------------------------------------------------------
    if (verbose) bsl::cout << "\nTESTING 'classify'"
                           << "\n=================="
                           << bsl::endl;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DF(X)
    {
        if (verbose) bsl::cout << "ValueType32" << bsl::endl;

        typedef Util::ValueType32 Type;

        Type SUBN_P  =              Util::denormMin32();
        Type SUBN_N  = Util::negate(Util::denormMin32());
        Type INF_P   =              Util::infinity32();
        Type INF_N   = Util::negate(Util::infinity32());
        Type NAN_Q_P =              Util::quietNaN32();
        Type NAN_Q_N = Util::negate(Util::quietNaN32());
        Type NAN_S_P =              Util::signalingNaN32();
        Type NAN_S_N = Util::negate(Util::signalingNaN32());
        Type MAX_P   =              Util::max32();
        Type MAX_N   = Util::negate(Util::max32());
        Type MIN_P   =              Util::min32();
        Type MIN_N   = Util::negate(Util::min32());

        // the most left 4 bits of the significand are in the range 8 to 9.
        Type SPE_8_P = DEC( 8.999999e+0);
        Type SPE_8_N = DEC(-8.999999e+0);
        Type SPE_9_P = DEC( 9.000001e+10);
        Type SPE_9_N = DEC(-9.000001e+10);

        static const struct {
            int          d_line;          // line
            Type         d_decimalValue;  // value to classify
            int          d_class;         // expected value's class
        } DATA[] = {
            // LINE  VALUE       CLASS
            // ----  ----------  ------------

            // Test zero values
            {  L_,   DEC( 0.0),  FP_ZERO      },
            {  L_,   DEC(-0.0),  FP_ZERO      },

            // Test special encoding values
            {  L_,   INF_P,      FP_INFINITE  },
            {  L_,   INF_N,      FP_INFINITE  },
            {  L_,   NAN_Q_P,    FP_NAN       },
            {  L_,   NAN_Q_N,    FP_NAN       },
            {  L_,   NAN_S_P,    FP_NAN       },
            {  L_,   NAN_S_N,    FP_NAN       },
            {  L_,   SUBN_P,     FP_SUBNORMAL },
            {  L_,   SUBN_N,     FP_SUBNORMAL },
            {  L_,   SPE_8_P,    FP_NORMAL    },
            {  L_,   SPE_8_N,    FP_NORMAL    },
            {  L_,   SPE_9_P,    FP_NORMAL    },
            {  L_,   SPE_9_N,    FP_NORMAL    },

            // Test boundary values
            {  L_,   MIN_P,      FP_NORMAL    },
            {  L_,   MIN_N,      FP_NORMAL    },
            {  L_,   MAX_P,      FP_NORMAL    },
            {  L_,   MAX_N,      FP_NORMAL    },

            // Test arbitrary values
            {  L_,   DEC( 1.0),  FP_NORMAL    },
            {  L_,   DEC(-1.0),  FP_NORMAL    },
            {  L_,   DEC( 0.1),  FP_NORMAL    },
            {  L_,   DEC(-0.1),  FP_NORMAL    },
            {  L_,   DEC( 4.25), FP_NORMAL    },
            {  L_,   DEC(-4.25), FP_NORMAL    },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE  = DATA[ti].d_line;
            const Type VALUE = DATA[ti].d_decimalValue;
            const int  CLASS = DATA[ti].d_class;

            if (veryVerbose) {
                P_(LINE); P(CLASS);
            }

            int  cl = Util::classify(VALUE);
            ASSERTV(LINE, CLASS, cl, CLASS ==  cl);
        }
    }
#undef DEC
#define DEC(X) BDLDFP_DECIMALIMPUTIL_DD(X)
    {
        if (verbose) bsl::cout << "ValueType64" << bsl::endl;

        typedef Util::ValueType64 Type;

        Type SUBN_P  =              Util::denormMin64();
        Type SUBN_N  = Util::negate(Util::denormMin64());
        Type INF_P   =              Util::infinity64();
        Type INF_N   = Util::negate(Util::infinity64());
        Type NAN_Q_P =              Util::quietNaN64();
        Type NAN_Q_N = Util::negate(Util::quietNaN64());
        Type NAN_S_P =              Util::signalingNaN64();
        Type NAN_S_N = Util::negate(Util::signalingNaN64());
        Type MAX_P   =              Util::max64();
        Type MAX_N   = Util::negate(Util::max64());
        Type MIN_P   =              Util::min64();
        Type MIN_N   = Util::negate(Util::min64());

        // the most left 4 bits of the significand are in the range 8 to 9.
        Type SPE_8_P = DEC( 8.999999999999999e+0);
        Type SPE_8_N = DEC(-8.999999999999999e+0);
        Type SPE_9_P = DEC( 9.000000000000001e+10);
        Type SPE_9_N = DEC(-9.000000000000001e+10);

        static const struct {
            int          d_line;          // line
            Type         d_decimalValue;  // value to classify
            int          d_class;         // expected value's class
        } DATA[] = {
            // LINE  VALUE       CLASS
            // ----  ----------  -----------

            // Test zero values
            {  L_,   DEC( 0.0),  FP_ZERO      },
            {  L_,   DEC(-0.0),  FP_ZERO      },

            // Test special encoding values
            {  L_,   INF_P,      FP_INFINITE  },
            {  L_,   INF_N,      FP_INFINITE  },
            {  L_,   NAN_Q_P,    FP_NAN       },
            {  L_,   NAN_Q_N,    FP_NAN       },
            {  L_,   NAN_S_P,    FP_NAN       },
            {  L_,   NAN_S_N,    FP_NAN       },
            {  L_,   SUBN_P,     FP_SUBNORMAL },
            {  L_,   SUBN_N,     FP_SUBNORMAL },
            {  L_,   SPE_8_P,    FP_NORMAL    },
            {  L_,   SPE_8_N,    FP_NORMAL    },
            {  L_,   SPE_9_P,    FP_NORMAL    },
            {  L_,   SPE_9_N,    FP_NORMAL    },

            // Test boundary values
            {  L_,   MIN_P,      FP_NORMAL    },
            {  L_,   MIN_N,      FP_NORMAL    },
            {  L_,   MAX_P,      FP_NORMAL    },
            {  L_,   MAX_N,      FP_NORMAL    },

            // Test arbitrary values
            {  L_,   DEC( 1.0),  FP_NORMAL    },
            {  L_,   DEC(-1.0),  FP_NORMAL    },
            {  L_,   DEC( 0.1),  FP_NORMAL    },
            {  L_,   DEC(-0.1),  FP_NORMAL    },
            {  L_,   DEC( 4.25), FP_NORMAL    },
            {  L_,   DEC(-4.25), FP_NORMAL    },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE  = DATA[ti].d_line;
            const Type VALUE = DATA[ti].d_decimalValue;
            const int  CLASS = DATA[ti].d_class;

            if (veryVerbose) {
                P_(LINE); P(CLASS);
            }

            int  cl = Util::classify(VALUE);
            ASSERTV(LINE, CLASS, cl, CLASS ==  cl);
        }
    }
#undef DEC
#define DEC(X) BDLDFP_DECIMALIMPUTIL_DL(X)
    {
        if (verbose) bsl::cout << "ValueType128" << bsl::endl;

        typedef Util::ValueType128 Type;

        Type SUBN_P  =              Util::denormMin128();
        Type SUBN_N  = Util::negate(Util::denormMin128());
        Type INF_P   =              Util::infinity128();
        Type INF_N   = Util::negate(Util::infinity128());
        Type NAN_Q_P =              Util::quietNaN128();
        Type NAN_Q_N = Util::negate(Util::quietNaN128());
        Type NAN_S_P =              Util::signalingNaN128();
        Type NAN_S_N = Util::negate(Util::signalingNaN128());
        Type MAX_P   =              Util::max128();
        Type MAX_N   = Util::negate(Util::max128());
        Type MIN_P   =              Util::min128();
        Type MIN_N   = Util::negate(Util::min128());
        Type V1_P    = Util::add(
                               Util::uint64ToDecimal128(0xFFFFFFFFFFFFFFFFull),
                               Util::uint64ToDecimal128( 1));
        Type V1_N    = Util::negate(V1_P);
        Type V2_P    = Util::add(
                          Util::multiply(V1_P, Util::uint64ToDecimal128(0x10)),
                          Util::uint64ToDecimal128(0x50));
        Type V2_N    = Util::negate(V2_P);

        static const struct {
            int          d_line;          // line
            Type         d_decimalValue;  // value to classify
            int          d_class;         // expected value's class
        } DATA[] = {
        // LINE  VALUE       CLASS
        // ----  ----------  ------------

        // Test zero values
        {  L_,   DEC( 0.0),  FP_ZERO      },
        {  L_,   DEC(-0.0),  FP_ZERO      },

        // Test special encoding values
        {  L_,   INF_P,      FP_INFINITE  },
        {  L_,   INF_N,      FP_INFINITE  },
        {  L_,   NAN_Q_P,    FP_NAN       },
        {  L_,   NAN_Q_N,    FP_NAN       },
        {  L_,   NAN_S_P,    FP_NAN       },
        {  L_,   NAN_S_N,    FP_NAN       },
        {  L_,   SUBN_P,     FP_SUBNORMAL },
        {  L_,   SUBN_N,     FP_SUBNORMAL },

        // Test boundary values
        {  L_,   MIN_P,      FP_NORMAL    },
        {  L_,   MIN_N,      FP_NORMAL    },
        {  L_,   MAX_P,      FP_NORMAL    },
        {  L_,   MAX_N,      FP_NORMAL    },
        // Test arbitrary values
        {  L_,   DEC( 1.0),  FP_NORMAL    },
        {  L_,   DEC(-1.0),  FP_NORMAL    },
        {  L_,   DEC( 0.1),  FP_NORMAL    },
        {  L_,   DEC(-0.1),  FP_NORMAL    },
        {  L_,   DEC( 4.25), FP_NORMAL    },
        {  L_,   DEC(-4.25), FP_NORMAL    },
        {  L_,   V1_P,       FP_NORMAL    },
        {  L_,   V1_N,       FP_NORMAL    },
        {  L_,   V2_P,       FP_NORMAL    },
        {  L_,   V2_N,       FP_NORMAL    },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE  = DATA[ti].d_line;
            const Type VALUE = DATA[ti].d_decimalValue;
            const int  CLASS = DATA[ti].d_class;

            if (veryVerbose) {
                P_(LINE); P(CLASS);
            }

            int  cl = Util::classify(VALUE);
            ASSERTV(LINE, CLASS, cl, CLASS ==  cl);
        }
    }
#undef DEC
}

void TestDriver::testCase24()
{
    // ------------------------------------------------------------------------
    // TESTING decompose
    //
    // Concerns:
    //: 1 Finite decimal value decomposed using 'decompose' functions can be
    //:   reconstructed to the value equal to the original one using
    //:   'sign', 'significand' and 'exponent' values.
    //:
    //: 2 Special encoding values having the 2 bits after the sign set to '11'
    //:   are decomposed either into finite value if at least one of the next
    //:   two bits are set to '0' or decomposed into 'Inf' or 'NaN' type
    //:   values otherwise.
    //:
    //: 3 QoI: asserted precondition violations are detected when enabled.
    //
    // Plan:
    //: 1 Try decomposing a variety of different valid values including minimum
    //:   and maximum values and special values such as 'NaN' and 'Inf' into
    //:   sign, significand and exponent compartments.  Verify returned values.
    //:   Restore the value using 'sign', significand' and 'exponent' parts and
    //:   check that if the value is not a special (infinity or NaNs), it is
    //:   restored into the value equal to the original one.  (C-1..2)
    //:
    //: 2 Verify that, in appropriate build modes, defensive checks are
    //:   triggered for invalid attribute values, but not triggered for
    //:   adjacent valid ones.  (C-3)
    //
    // Testing:
    //   int decompose(int *, unsigned int *, int *, ValueType32);
    //   int decompose(int *, bsls::Types::Uint64 *, int *, ValueType64);
    //   int decompose(int *, Uint128 *, int *, ValueType128);
    // --------------------------------------------------------------------
    if (verbose) bsl::cout << "\nTESTING DECOMPOSE METHODS"
                           << "\n========================="
                           << bsl::endl;

#define DEC(X) BDLDFP_DECIMALIMPUTIL_DF(X)
    {
        if (verbose) bsl::cout << "ValueType32" << bsl::endl;

        typedef Util::ValueType32 Type;

        Type SUBN_P  =              Util::denormMin32();
        Type SUBN_N  = Util::negate(Util::denormMin32());
        Type INF_P   =              Util::infinity32();
        Type INF_N   = Util::negate(Util::infinity32());
        Type NAN_Q_P =              Util::quietNaN32();
        Type NAN_Q_N = Util::negate(Util::quietNaN32());
        Type NAN_S_P =              Util::signalingNaN32();
        Type NAN_S_N = Util::negate(Util::signalingNaN32());
        Type MAX_P   =              Util::max32();
        Type MAX_N   = Util::negate(Util::max32());
        Type MIN_P   =              Util::min32();
        Type MIN_N   = Util::negate(Util::min32());

        // the most left 4 bits of the significand are in the range 8 to 9.
        Type SPE_8_P = DEC( 8.999999e+0);
        Type SPE_8_N = DEC(-8.999999e+0);
        Type SPE_9_P = DEC( 9.000001e+10);
        Type SPE_9_N = DEC(-9.000001e+10);

        static const struct {
            int          d_line;
            Type         d_decimalValue;
            int          d_class;         // classification
            int          d_sign;
            unsigned int d_significand;
            int          d_exponent;
        } DATA[] = {
            // LINE  VALUE       CLASS         SIGN  SIGNIFICAND    EXP
            // ----  ----------  -------       ----  -----------    ----

            // Test zero values
            {  L_,   DEC( 0.0),  FP_ZERO,       1,             0,    -1 },
            {  L_,   DEC(-0.0),  FP_ZERO,      -1,             0,    -1 },

            // Test special encoding values
            {  L_,   INF_P,      FP_INFINITE,   1,      0x800000,  0xc0 },
            {  L_,   INF_N,      FP_INFINITE,  -1,      0x800000,  0xc0 },
            {  L_,   NAN_Q_P,    FP_NAN,        1,      0x800000,  0xe0 },
            {  L_,   NAN_Q_N,    FP_NAN,       -1,      0x800000,  0xe0 },
            {  L_,   NAN_S_P,    FP_NAN,        1,      0x800000,  0xf0 },
            {  L_,   NAN_S_N,    FP_NAN,       -1,      0x800000,  0xf0 },
            {  L_,   SUBN_P,     FP_SUBNORMAL,  1,             1,  -101 },
            {  L_,   SUBN_N,     FP_SUBNORMAL, -1,             1,  -101 },
            {  L_,   SPE_8_P,    FP_NORMAL,     1,       8999999,    -6 },
            {  L_,   SPE_8_N,    FP_NORMAL,    -1,       8999999,    -6 },
            {  L_,   SPE_9_P,    FP_NORMAL,     1,       9000001,     4 },
            {  L_,   SPE_9_N,    FP_NORMAL,    -1,       9000001,     4 },

            // Test boundary values
            {  L_,   MIN_P,      FP_NORMAL,     1,             1,   -95 },
            {  L_,   MIN_N,      FP_NORMAL,    -1,             1,   -95 },
            {  L_,   MAX_P,      FP_NORMAL,     1,       9999999,    90 },
            {  L_,   MAX_N,      FP_NORMAL,    -1,       9999999,    90 },

            // Test arbitrary values
            {  L_,   DEC( 1.0),  FP_NORMAL,     1,            10,    -1 },
            {  L_,   DEC(-1.0),  FP_NORMAL,    -1,            10,    -1 },
            {  L_,   DEC( 0.1),  FP_NORMAL,     1,             1,    -1 },
            {  L_,   DEC(-0.1),  FP_NORMAL,    -1,             1,    -1 },
            {  L_,   DEC( 4.25), FP_NORMAL,     1,           425,    -2 },
            {  L_,   DEC(-4.25), FP_NORMAL,    -1,           425,    -2 },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        if (verbose) cout << "\tTesting behavior." << endl;

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int           LINE        = DATA[ti].d_line;
            const Type          VALUE       = DATA[ti].d_decimalValue;
            const int           CLASS       = DATA[ti].d_class;
            const int           SIGN        = DATA[ti].d_sign;
            const unsigned int  SIGNIFICAND = DATA[ti].d_significand;
            const int           EXPONENT    = DATA[ti].d_exponent;

            if (veryVerbose) {
                P_(LINE); P_(CLASS); P_(SIGN); P_(SIGNIFICAND); P(EXPONENT);
            }

            int          sign;
            unsigned int significand;
            int          exponent;
            int          cl = Util::decompose(&sign,
                                              &significand,
                                              &exponent,
                                              VALUE);

            ASSERTV(LINE, CLASS, cl,   CLASS ==  cl);
            ASSERTV(LINE, SIGN,  sign, SIGN  == sign);
            ASSERTV(LINE,
                    significand,
                    SIGNIFICAND,
                    SIGNIFICAND == significand);
            ASSERTV(LINE,
                    exponent,
                    EXPONENT,
                    EXPONENT == exponent);

            if ((CLASS != FP_NAN) && (CLASS != FP_INFINITE)) {
                Type input = Util::makeDecimalRaw32(sign * significand,
                                                    exponent);
                ASSERTV(LINE, Util::equal(VALUE, input));
            }
        }

        if (verbose) cout << "\tNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            const Type    TEMP = DEC( 0.0);
            int           SIGN;
            unsigned int  SIGNIFICAND;
            int           EXPONENT;
            int           *VALID_SIGN(&SIGN);
            unsigned int  *VALID_SIGNIFICAND(&SIGNIFICAND);
            int           *VALID_EXPONENT(&EXPONENT);
            int           *INVALID_SIGN(0);
            unsigned int  *INVALID_SIGNIFICAND(0);
            int           *INVALID_EXPONENT(0);

            ASSERT_PASS(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(INVALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        INVALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        INVALID_EXPONENT,
                                        TEMP));
        }
    }
#undef DEC
#define DEC(X) BDLDFP_DECIMALIMPUTIL_DD(X)
    {
        if (verbose) bsl::cout << "ValueType64" << bsl::endl;

        typedef Util::ValueType64 Type;

        Type SUBN_P  =              Util::denormMin64();
        Type SUBN_N  = Util::negate(Util::denormMin64());
        Type INF_P   =              Util::infinity64();
        Type INF_N   = Util::negate(Util::infinity64());
        Type NAN_Q_P =              Util::quietNaN64();
        Type NAN_Q_N = Util::negate(Util::quietNaN64());
        Type NAN_S_P =              Util::signalingNaN64();
        Type NAN_S_N = Util::negate(Util::signalingNaN64());
        Type MAX_P   =              Util::max64();
        Type MAX_N   = Util::negate(Util::max64());
        Type MIN_P   =              Util::min64();
        Type MIN_N   = Util::negate(Util::min64());

        // the most left 4 bits of the significand are in the range 8 to 9.
        Type SPE_8_P = DEC( 8.999999999999999e+0);
        Type SPE_8_N = DEC(-8.999999999999999e+0);
        Type SPE_9_P = DEC( 9.000000000000001e+10);
        Type SPE_9_N = DEC(-9.000000000000001e+10);

        static const struct {
            int                 d_line;
            Type                d_decimalValue;
            int                 d_class;         // classification
            int                 d_sign;
            bsls::Types::Uint64 d_significand;
            int                 d_exponent;
        } DATA[] = {
            // L   VALUE       CLASS       SIGN  SIGNIFICAND          EXPONENT
            // --- ----------  ----------- ----  -------------------- --------

            // Test zero values
            {  L_, DEC( 0.0),  FP_ZERO,       1,                   0,     -1 },
            {  L_, DEC(-0.0),  FP_ZERO,      -1,                   0,     -1 },

            // Test special encoding values
            {  L_, INF_P,      FP_INFINITE,   1, 0x20000000000000ull,  0x300 },
            {  L_, INF_N,      FP_INFINITE,  -1, 0x20000000000000ull,  0x300 },
            {  L_, NAN_Q_P,    FP_NAN,        1, 0x20000000000000ull,  0x380 },
            {  L_, NAN_Q_N,    FP_NAN,       -1, 0x20000000000000ull,  0x380 },
            {  L_, NAN_S_P,    FP_NAN,        1, 0x20000000000000ull,  0x3c0 },
            {  L_, NAN_S_N,    FP_NAN,       -1, 0x20000000000000ull,  0x3c0 },
            {  L_, SUBN_P,     FP_SUBNORMAL,  1,                   1,   -398 },
            {  L_, SUBN_N,     FP_SUBNORMAL, -1,                   1,   -398 },
            {  L_, SPE_8_P,    FP_NORMAL,     1, 8999999999999999ull,    -15 },
            {  L_, SPE_8_N,    FP_NORMAL,    -1, 8999999999999999ull,    -15 },
            {  L_, SPE_9_P,    FP_NORMAL,     1, 9000000000000001ull,     -5 },
            {  L_, SPE_9_N,    FP_NORMAL,    -1, 9000000000000001ull,     -5 },

            // Test boundary values
            {  L_, MIN_P,      FP_NORMAL,     1,                   1,   -383 },
            {  L_, MIN_N,      FP_NORMAL,    -1,                   1,   -383 },
            {  L_, MAX_P,      FP_NORMAL,     1, 9999999999999999ull,    369 },
            {  L_, MAX_N,      FP_NORMAL,    -1, 9999999999999999ull,    369 },

            // Test arbitrary values
            {  L_, DEC( 1.0),  FP_NORMAL,     1,                  10,     -1 },
            {  L_, DEC(-1.0),  FP_NORMAL,    -1,                  10,     -1 },
            {  L_, DEC( 0.1),  FP_NORMAL,     1,                   1,     -1 },
            {  L_, DEC(-0.1),  FP_NORMAL,    -1,                   1,     -1 },
            {  L_, DEC( 4.25), FP_NORMAL,     1,                 425,     -2 },
            {  L_, DEC(-4.25), FP_NORMAL,    -1,                 425,     -2 },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        if (verbose) cout << "\tTesting behavior." << endl;

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int                 LINE        = DATA[ti].d_line;
            const Type                VALUE       = DATA[ti].d_decimalValue;
            const int                 CLASS       = DATA[ti].d_class;
            const int                 SIGN        = DATA[ti].d_sign;
            const bsls::Types::Uint64 SIGNIFICAND = DATA[ti].d_significand;
            const int                 EXPONENT    = DATA[ti].d_exponent;

            if (veryVerbose) {
                P_(LINE); P_(CLASS); P_(SIGN); P_(SIGNIFICAND); P(EXPONENT);
            }

            int                 sign;
            bsls::Types::Uint64 significand;
            int                 exponent;
            int                 cl = Util::decompose(&sign,
                                                     &significand,
                                                     &exponent,
                                                     VALUE);

            ASSERTV(LINE, CLASS, cl,   CLASS ==  cl);
            ASSERTV(LINE, SIGN,  sign, SIGN  == sign);
            ASSERTV(LINE,
                    significand,
                    SIGNIFICAND,
                    SIGNIFICAND == significand);
            ASSERTV(LINE,
                    exponent,
                    EXPONENT,
                    EXPONENT == exponent);

            if ((CLASS != FP_NAN) && (CLASS != FP_INFINITE)) {
                Type input = Util::makeDecimalRaw64(significand, exponent);
                input = (sign == 1) ? input : Util::negate(input);

                ASSERTV(LINE, Util::equal(VALUE, input));
            }
        }

        if (verbose) cout << "\tNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            const Type           TEMP = DEC( 0.0);
            int                  SIGN;
            bsls::Types::Uint64  SIGNIFICAND;
            int                  EXPONENT;
            int                 *VALID_SIGN(&SIGN);
            bsls::Types::Uint64 *VALID_SIGNIFICAND(&SIGNIFICAND);
            int                 *VALID_EXPONENT(&EXPONENT);
            int                 *INVALID_SIGN(0);
            bsls::Types::Uint64 *INVALID_SIGNIFICAND(0);
            int                 *INVALID_EXPONENT(0);

            ASSERT_PASS(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(INVALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        INVALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        INVALID_EXPONENT,
                                        TEMP));
        }
    }
#undef DEC
#define DEC(X) BDLDFP_DECIMALIMPUTIL_DL(X)
    {
        if (verbose) bsl::cout << "ValueType128" << bsl::endl;

        typedef Util::ValueType128 Type;

        Type SUBN_P  =              Util::denormMin128();
        Type SUBN_N  = Util::negate(Util::denormMin128());
        Type INF_P   =              Util::infinity128();
        Type INF_N   = Util::negate(Util::infinity128());
        Type NAN_Q_P =              Util::quietNaN128();
        Type NAN_Q_N = Util::negate(Util::quietNaN128());
        Type NAN_S_P =              Util::signalingNaN128();
        Type NAN_S_N = Util::negate(Util::signalingNaN128());
        Type MAX_P   =              Util::max128();
        Type MAX_N   = Util::negate(Util::max128());
        Type MIN_P   =              Util::min128();
        Type MIN_N   = Util::negate(Util::min128());
        Type V1_P    = Util::add(
                               Util::uint64ToDecimal128(0xFFFFFFFFFFFFFFFFull),
                               Util::uint64ToDecimal128( 1));
        Type V1_N    = Util::negate(V1_P);
        Type V2_P    = Util::add(
                          Util::multiply(V1_P, Util::uint64ToDecimal128(0x10)),
                          Util::uint64ToDecimal128(0x50));
        Type V2_N    = Util::negate(V2_P);

        static const struct {
            int                 d_line;
            Type                d_decimalValue;
            int                 d_class;         // classification
            int                 d_sign;
            bsls::Types::Uint64 d_significandH;
            bsls::Types::Uint64 d_significandL;
            int                 d_exponent;
        } DATA[] = {
        // L   VALUE       CLASS        SIGN  SIGNIFICAND HIGH,    EXPONENT
        //                                    SIGNIFICAND LOW
        // --- ----------  -------      ----  -------------------  ---------

        // Test zero values
        {  L_, DEC( 0.0),  FP_ZERO,       1,                     0,
                                                                 0,       -1 },
        {  L_, DEC(-0.0),  FP_ZERO,      -1,                     0,
                                                                 0,       -1 },

        // Test special encoding values
        {  L_, INF_P,      FP_INFINITE,   1,   0x20000000000000ull,
                                                                 0,   0x3000 },
        {  L_, INF_N,      FP_INFINITE,  -1,   0x20000000000000ull,
                                                                 0,   0x3000 },
        {  L_, NAN_Q_P,    FP_NAN,        1,   0x20000000000000ull,
                                                                 0,   0x3800 },
        {  L_, NAN_Q_N,    FP_NAN,       -1,   0x20000000000000ull,
                                                                 0,   0x3800 },
        {  L_, NAN_S_P,    FP_NAN,        1,   0x20000000000000ull,
                                                                 0,   0x3c00 },
        {  L_, NAN_S_N,    FP_NAN,       -1,   0x20000000000000ull,
                                                                 0,   0x3c00 },
        {  L_, SUBN_P,     FP_SUBNORMAL,  1,                     0,
                                                                 1,    -6176 },
        {  L_, SUBN_N,     FP_SUBNORMAL, -1,                     0,
                                                                 1,    -6176 },

            // // Test boundary values
        {  L_, MIN_P,      FP_NORMAL,     1,                     0,
                                                                 1,    -6143 },
        {  L_, MIN_N,      FP_NORMAL,    -1,                     0,
                                                                 1,    -6143 },
        {  L_, MAX_P,      FP_NORMAL,     1,    0x1ED09BEAD87C0ull,
                                             0x378D8E63FFFFFFFFull,     6111 },
        {  L_, MAX_N,      FP_NORMAL,    -1,    0x1ED09BEAD87C0ull,
                                             0x378D8E63FFFFFFFFull,     6111 },
            // // Test arbitrary values
        {  L_, DEC( 1.0),  FP_NORMAL,     1,                     0,
                                                                10,       -1 },
        {  L_, DEC(-1.0),  FP_NORMAL,    -1,                     0,
                                                                10,       -1 },
        {  L_, DEC( 0.1),  FP_NORMAL,     1,                     0,
                                                                 1,       -1 },
        {  L_, DEC(-0.1),  FP_NORMAL,    -1,                     0,
                                                                 1,       -1 },
        {  L_, DEC( 4.25), FP_NORMAL,     1,                     0,
                                                               425,       -2 },
        {  L_, DEC(-4.25), FP_NORMAL,    -1,                     0,
                                                               425,       -2 },
        {  L_, V1_P,       FP_NORMAL,     1,                     1,
                                                                 0,        0 },
        {  L_, V1_N,       FP_NORMAL,    -1,                     1,
                                                                 0,        0 },
        {  L_, V2_P,       FP_NORMAL,     1,                  0x10,
                                                              0x50,        0 },
        {  L_, V2_N,       FP_NORMAL,    -1,                  0x10,
                                                              0x50,        0 },
        };
        enum { NUM_DATA = sizeof DATA / sizeof *DATA };

        if (verbose) cout << "\tTesting behavior." << endl;

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int                 LINE          = DATA[ti].d_line;
            const Type                VALUE         = DATA[ti].d_decimalValue;
            const int                 CLASS         = DATA[ti].d_class;
            const int                 SIGN          = DATA[ti].d_sign;
            const bsls::Types::Uint64 SIGNIFICAND_H = DATA[ti].d_significandH;
            const bsls::Types::Uint64 SIGNIFICAND_L = DATA[ti].d_significandL;
            const int                 EXPONENT      = DATA[ti].d_exponent;

            if (veryVerbose) {
                P_(LINE); P_(CLASS); P_(SIGN);
                P_(SIGNIFICAND_H); P_(SIGNIFICAND_L);
                P(EXPONENT);
            }

            int           sign;
            BDEC::Uint128 significand;
            int           exponent;
            int           cl = Util::decompose(&sign,
                                               &significand,
                                               &exponent,
                                               VALUE);

            ASSERTV(LINE, CLASS, cl,   CLASS ==  cl);
            ASSERTV(LINE, SIGN,  sign, SIGN  == sign);
            ASSERTV(LINE,
                    SIGNIFICAND_H,
                    significand.high(),
                    SIGNIFICAND_H == significand.high());
            ASSERTV(LINE,
                    SIGNIFICAND_L,
                    significand.low(),
                    SIGNIFICAND_L == significand.low());
            ASSERTV(LINE,
                    exponent,
                    EXPONENT,
                    EXPONENT == exponent);

            if ((CLASS != FP_NAN) && (CLASS != FP_INFINITE)) {
                const Type MOVE_LEFT_64 = Util::add(
                               Util::uint64ToDecimal128(0xFFFFFFFFFFFFFFFFull),
                               Util::uint64ToDecimal128(1));
                const Type SIGNIFICAND = Util::add(
                               Util::multiply(
                                  Util::uint64ToDecimal128(significand.high()),
                                  MOVE_LEFT_64),
                               Util::uint64ToDecimal128(significand.low()));
                Type       input = Util::scaleB(SIGNIFICAND, exponent);

                input = (sign == 1) ? input : Util::negate(input);
                ASSERTV(LINE, Util::equal(VALUE, input));
            }
        }

        if (verbose) cout << "\tNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            const Type     TEMP = DEC( 0.0);
            int            SIGN;
            BDEC::Uint128  SIGNIFICAND;
            int            EXPONENT;
            int           *VALID_SIGN(&SIGN);
            BDEC::Uint128 *VALID_SIGNIFICAND(&SIGNIFICAND);
            int           *VALID_EXPONENT(&EXPONENT);
            int           *INVALID_SIGN(0);
            BDEC::Uint128 *INVALID_SIGNIFICAND(0);
            int           *INVALID_EXPONENT(0);

            ASSERT_PASS(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(INVALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        INVALID_SIGNIFICAND,
                                        VALID_EXPONENT,
                                        TEMP));
            ASSERT_FAIL(Util::decompose(VALID_SIGN,
                                        VALID_SIGNIFICAND,
                                        INVALID_EXPONENT,
                                        TEMP));
        }
    }
#undef DEC
}

void TestDriver::testCase23()
{
    // ------------------------------------------------------------------------
    // TESTING BOUNDARY VALUES FUNCTIONS
    //
    // Concerns:
    //: 1 All functions return expected values.
    //
    // Plan:
    //: 1 Use the 'parseXX' function to reate model objects, having special
    //:   values excluding NaN.  Call appropriate function and compare returned
    //:   result with model object.
    //:
    //: 2 As NaN can't be compared with any object, create a mask to verify
    //:   representation of returned results for 'signalingNaN' and 'quietNaN'.
    //:   (C-1)
    //
    // Testing:
    //   ValueType32 min32();
    //   ValueType32 max32();
    //   ValueType32 epsilon32();
    //   ValueType32 roundError32();
    //   ValueType32 denormMin32();
    //   ValueType32 infinity32();
    //   ValueType32 quietNaN32();
    //   ValueType32 signalingNaN32();
    //   ValueType64 min64();
    //   ValueType64 max64();
    //   ValueType64 epsilon64();
    //   ValueType64 roundError64();
    //   ValueType64 denormMin64();
    //   ValueType64 infinity64();
    //   ValueType64 quietNaN64();
    //   ValueType64 signalingNaN64();
    //   ValueType128 min128();
    //   ValueType128 max128();
    //   ValueType128 epsilon128();
    //   ValueType128 roundError128();
    //   ValueType128 denormMin128();
    //   ValueType128 infinity128();
    //   ValueType128 quietNaN128();
    //   ValueType128 signalingNaN128();
    // --------------------------------------------------------------------
    if (verbose) bsl::cout << "\nTESTING BOUNDARY VALUES FUNCTIONS"
                           << "\n================================="
                           << bsl::endl;

    if (verbose) bsl::cout << "ValueType32" << bsl::endl;
    {
        typedef Util::ValueType32 Type;

        const Type MIN         = Util::parse32("+1e-95");
        const Type MAX         = Util::parse32("+9.999999e+96");
        const Type EPSILON     = Util::parse32("+1e-6");
        const Type ROUND_ERROR = Util::parse32("1.0");
        const Type DENORM_MIN  = Util::parse32("+0.000001E-95");
        const Type INF         = Util::parse32("Inf");

        Type value;

        value = Util::min32();
        ASSERTV(Util::equal(MIN, value));

        value = Util::max32();
        ASSERTV(Util::equal(MAX, value));

        value = Util::epsilon32();
        ASSERTV(Util::equal(EPSILON, value));

        value = Util::roundError32();
        ASSERTV(Util::equal(ROUND_ERROR, value));

        value = Util::denormMin32();
        ASSERTV(Util::equal(DENORM_MIN, value));

        value = Util::infinity32();
        ASSERTV(Util::equal(INF, value));

        // As we can't compare NaNs, we will check combination field and the
        // most significant bit of exponent continuation field.

        unsigned int QNAN_MASK = 0x7C000000;  // 01111100 00...0
        unsigned int SNAN_MASK = 0x7E000000;  // 01111110 00...0

        value = Util::signalingNaN32();
        ASSERT(SNAN_MASK == (value.d_raw & SNAN_MASK));

        value = Util::quietNaN32();
        ASSERT(QNAN_MASK == (value.d_raw & QNAN_MASK));
    }

    if (verbose) bsl::cout << "ValueType64" << bsl::endl;
    {
        typedef Util::ValueType64 Type;

        const Type MIN         = Util::parse64("+1e-383");
        const Type MAX         = Util::parse64("+9.999999999999999e+384");
        const Type EPSILON     = Util::parse64("+1e-15");
        const Type ROUND_ERROR = Util::parse64("1.0");
        const Type DENORM_MIN  = Util::parse64("+0.000000000000001e-383");
        const Type INF         = Util::parse64("Inf");

        Type value;

        value = Util::min64();
        ASSERTV(Util::equal(MIN, value));

        value = Util::max64();
        ASSERTV(Util::equal(MAX, value));

        value = Util::epsilon64();
        ASSERTV(Util::equal(EPSILON, value));

        value = Util::roundError64();
        ASSERTV(Util::equal(ROUND_ERROR, value));

        value = Util::denormMin64();
        ASSERTV(Util::equal(DENORM_MIN, value));

        value = Util::infinity64();
        ASSERTV(Util::equal(INF, value));

        // As we can't compare NaNs, we will check combination field and the
        // most significant bit of exponent continuation field.

        bsls::Types::Uint64 QNAN_MASK = 0x7C00000000000000ULL;
                                                             // 01111100 00...0
        bsls::Types::Uint64 SNAN_MASK = 0x7E00000000000000ULL;
                                                             // 01111110 00...0

        value = Util::signalingNaN64();
        bsls::Types::Uint64 raw;
#ifdef BDLDFP_DECIMALPLATFORM_INTELDFP
        raw = value.d_raw;
#else
        raw = *value.longs;
#endif
        ASSERT(SNAN_MASK == (raw & SNAN_MASK));

        value = Util::quietNaN64();
#ifdef BDLDFP_DECIMALPLATFORM_INTELDFP
        raw = value.d_raw;
#else
        raw = *value.longs;
#endif
        ASSERT(QNAN_MASK == (raw & QNAN_MASK));
    }

    if (verbose) bsl::cout << "ValueType128" << bsl::endl;
    {
        typedef Util::ValueType128 Type;

        const Type MIN         = Util::parse128("+1e-6143");
        const Type MAX         = Util::parse128(
                                 "+9.999999999999999999999999999999999e+6144");
        const Type EPSILON     = Util::parse128("+1e-33");
        const Type ROUND_ERROR = Util::parse128("1.0");
        const Type DENORM_MIN  = Util::parse128(
                                 "+0.000000000000000000000000000000001e-6143");
        const Type INF         = Util::parse128("Inf");

        Type value;

        value = Util::min128();
        ASSERTV(Util::equal(MIN, value));

        value = Util::max128();
        ASSERTV(Util::equal(MAX, value));

        value = Util::epsilon128();
        ASSERTV(Util::equal(EPSILON, value));

        value = Util::roundError128();
        ASSERTV(Util::equal(ROUND_ERROR, value));

        value = Util::denormMin128();
        ASSERTV(Util::equal(DENORM_MIN, value));

        value = Util::infinity128();
        ASSERTV(Util::equal(INF, value));

        // As we can't compare NaNs, we will check combination field and the
        // most significant bit of exponent continuation field.

        bsls::Types::Uint64 QNAN_MASK = 0x7C00000000000000ULL;
                                                             // 01111100 00...0
        bsls::Types::Uint64 SNAN_MASK = 0x7E00000000000000ULL;
                                                             // 01111110 00...0

        value = Util::signalingNaN128();
        bsls::Types::Uint64 raw;
#ifdef BDLDFP_DECIMALPLATFORM_INTELDFP
    #ifdef BSLS_PLATFORM_IS_BIG_ENDIAN
        raw = value.d_raw.w[0];
    #elif defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
        raw = value.d_raw.w[1];
    #endif
#else
    #ifdef BSLS_PLATFORM_IS_BIG_ENDIAN
        raw = *value.longs[0];
    #elif defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
        raw = *value.longs[1];
    #endif
#endif
        ASSERT(SNAN_MASK == (raw & SNAN_MASK));

        value = Util::quietNaN128();
#ifdef BDLDFP_DECIMALPLATFORM_INTELDFP
    #ifdef BSLS_PLATFORM_IS_BIG_ENDIAN
        raw = value.d_raw.w[0];
    #elif defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
        raw = value.d_raw.w[1];
    #endif
#else
    #ifdef BSLS_PLATFORM_IS_BIG_ENDIAN
        raw = *value.longs[0];
    #elif defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
        raw = *value.longs[1];
    #endif
#endif
        ASSERT(QNAN_MASK == (raw & QNAN_MASK));
    }
}

void TestDriver::testCase22()
{
    // ------------------------------------------------------------------------
    // TESTING CONVERSION FROM BINARY INTEGRAL
    //
    // Concerns:
    //:  1 Values in the implementation format are created faithfully and
    //:    correctly when converted from the BID format.
    //:
    //:  2 The value, after conversion, has the same cohort as the original
    //:    value.
    //:
    //:  3 32, 64, and 128 bit variations all work correctly.
    //:
    //:  4 Special cases, such as Infinity and NaN are represented correctly as
    //:    BID.
    //:
    //:  5 The implementation format values correctly survive round-trip
    //:    encoding.
    //
    // Plan:
    //:  1 Iterate through a set of test mantissa and convert them to BID, then
    //:    convert back to the implementation format, comparing the results.
    //:    (C-1..3)
    //:
    //:  2 Test the special case values explicitly, by converting to BID, then
    //:    using the conversion back.  Check that the properties of these
    //:    special cases hold.  (C-2..5)
    //
    // Testing
    //   convertFromBID(ValueType32)
    //   convertFromBID(ValueType64)
    //   convertFromBID(ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING CONVERSION FROM BINARY INTEGRAL" << endl
                      << "=======================================" << endl;

    // Test that with any of a set of exponents, we can convert 32-bit
    // values correctly to BID.

    // IMPLEMENTATION NOTE: This test case currently assumes that the
    // underlying implementation of Decimal arithmetic is 'BID' not 'DPD'.
    // This test driver will need to be updated to handle 'DPD'
    // implementations.

    {
        Util::ValueType32 testDecimal;
        DS::       Type32 witnessBID;
        Util::ValueType32 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw32(0, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw32(7, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw32(52, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertFromBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertFromBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw32(mantissa,
                                                         exponent);

                    witnessBID = Util::convertToBID(testDecimal);
                    witness = Util::convertFromBID(witnessBID);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType32 specialWitness;

        testDecimal    = Util::parse32("NaN");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse32("+Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse32("-Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 64-bit
    // values correctly to DPD.

    {
        Util::ValueType64 testDecimal;
        DS::       Type64 witnessBID;
        Util::ValueType64 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw64(0, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw64(7, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw64(52, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertFromBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertFromBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw64(mantissa,
                                                         exponent);

                    witnessBID = Util::convertToBID(testDecimal);
                    witness = Util::convertFromBID(witnessBID);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType64 specialWitness;

        testDecimal    = Util::parse64("NaN");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse64("+Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse64("-Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 128-bit
    // values correctly to DPD.

    {
        Util::ValueType128 testDecimal;
        DS::       Type128 witnessBID;
        Util::ValueType128 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw128(0, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw128(7, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw128(52, 0);
        witnessBID  = Util::convertToBID(testDecimal);
        witness     = Util::convertFromBID(witnessBID);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertFromBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertFromBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw128(mantissa,
                                                         exponent);

                    witnessBID = Util::convertToBID(testDecimal);
                    witness = Util::convertFromBID(witnessBID);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType128 specialWitness;

        testDecimal    = Util::parse128("NaN");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse128("+Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse128("-Inf");
        witnessBID     = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(witnessBID);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }
}

void TestDriver::testCase21()
{
    // ------------------------------------------------------------------------
    // TESTING CONVERSION TO BINARY INTEGRAL
    //
    // Concerns:
    //:  1 Values in the implementation format are represented faithfully and
    //:    correctly in the BID format, when converted.
    //:
    //:  2 The value, after conversion, has the same cohort as the original
    //:    value.
    //:
    //:  3 32, 64, and 128 bit variations all work correctly.
    //:
    //:  4 Special cases, such as Infinity and NaN are represented correctly as
    //:    BID.
    //
    // Plan:
    //:  1 Iterate through a set of test mantissa and convert them to BID,
    //:    comparing the result to a canonically constructed value in BID.
    //:    (C-1..3)
    //:
    //:  2 Test the special case values explicitly, by converting to BID, then
    //:    using the conversion back.  Check that the properties of these
    //:    special cases hold. (C-3,4)
    //
    // Testing
    //   convertToBID(ValueType32)
    //   convertToBID(ValueType64)
    //   convertToBID(ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING CONVERSION TO BINARY INTEGRAL" << endl
                      << "=====================================" << endl;

    // Test that with any of a set of exponents, we can convert 32-bit
    // values correctly to BID.

    // IMPLEMENTATION NOTE: This test case currently assumes that the
    // underlying implementation of Decimal arithmetic is 'BID' not 'DPD'.
    // This test driver will need to be updated to handle 'DPD'
    // implementations.

    {
        Util::ValueType32 testDecimal;
        DS::       Type32 testConvert;
        Util::ValueType32 witness;

                    // 0e0

        witness     =    Util::makeDecimalRaw32(0, 0);
        testDecimal =    Util::makeDecimalRaw32(0, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 7e0

        witness     =    Util::makeDecimalRaw32(7, 0);
        testDecimal =    Util::makeDecimalRaw32(7, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 52e0

        witness     =    Util::makeDecimalRaw32(52, 0);
        testDecimal =    Util::makeDecimalRaw32(52, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertToBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertToBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    witness     =    Util::makeDecimalRaw32(mantissa,
                                                            exponent);
                    testDecimal =    Util::makeDecimalRaw32(mantissa,
                                                            exponent);
                    testConvert =    Util::convertToBID(
                                                              testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));

                }
            }
        }

        Util::ValueType32 specialWitness;

        testDecimal    = Util::parse32("NaN");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse32("+Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse32("-Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 64-bit
    // values correctly to BID.

    {
        Util::ValueType64 testDecimal;
        DS::       Type64 testConvert;
        Util::ValueType64 witness;

                    // 0e0

        witness     =    Util::makeDecimalRaw64(0, 0);
        testDecimal =    Util::makeDecimalRaw64(0, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 7e0

        witness     =    Util::makeDecimalRaw64(7, 0);
        testDecimal =    Util::makeDecimalRaw64(7, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 52e0

        witness     =    Util::makeDecimalRaw64(52, 0);
        testDecimal =    Util::makeDecimalRaw64(52, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertToBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertToBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (mantissa <=  9999999999999999ll &&
                    mantissa >= -9999999999999999ll &&
                    exponent <= 369 && exponent >= -398) {

                    witness     =    Util::makeDecimalRaw64(mantissa,
                                                            exponent);
                    testDecimal =    Util::makeDecimalRaw64(mantissa,
                                                            exponent);
                    testConvert =    Util::convertToBID(
                                                              testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));
                }
            }
        }

        Util::ValueType64 specialWitness;

        testDecimal    = Util::parse64("NaN");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse64("+Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse64("-Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 128-bit
    // values correctly to BID.

    {
        Util::ValueType128 testDecimal;
        DS::       Type128 testConvert;
        Util::ValueType128 witness;

                    // 0e0

        witness     =    Util::makeDecimalRaw128(0, 0);
        testDecimal =    Util::makeDecimalRaw128(0, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 7e0

        witness     =    Util::makeDecimalRaw128(7, 0);
        testDecimal =    Util::makeDecimalRaw128(7, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // 52e0

        witness     =    Util::makeDecimalRaw128(52, 0);
        testDecimal =    Util::makeDecimalRaw128(52, 0);
        testConvert =    Util::convertToBID(testDecimal);

        ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertToBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertToBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (exponent <= 6111 && exponent >= -6176) {

                    witness     =    Util::makeDecimalRaw128(mantissa,
                                                            exponent);
                    testDecimal =    Util::makeDecimalRaw128(mantissa,
                                                            exponent);
                    testConvert =    Util::convertToBID(
                                                              testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));
                }
            }
        }

        Util::ValueType128 specialWitness;

        testDecimal    = Util::parse128("NaN");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse128("+Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse128("-Inf");
        testConvert    = Util::convertToBID(testDecimal);
        specialWitness = Util::convertFromBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }
}

void TestDriver::testCase20()
{
    // ------------------------------------------------------------------------
    // TESTING CONVERSION FROM DENSELY PACKED
    //
    // Concerns:
    //:  1 Values in the implementation format are created faithfully and
    //:    correctly when converted from  the DPD format.
    //:
    //:  2 The value, after conversion, has the same cohort as the original
    //:    value.
    //:
    //:  3 32, 64, and 128 bit variations all work correctly.
    //:
    //:  4 Special cases, such as Infinity and NaN are represented correctly as
    //:    DPD.
    //:
    //:  5 The implementation format values correctly survive round-trip
    //:    encoding.
    //
    // Plan:
    //:  1 Iterate through a set of test mantissa and convert them to DPD, then
    //:    convert back to the implementation format, comparing the results.
    //:    (C-1..3)
    //:
    //:  2 Test the special case values explicitly, by converting to DPD, then
    //:    using the conversion back.  Check that the properties of these
    //:    special cases hold.  (C-2..5)
    //
    // Testing
    //   convertDPDtoBID(ValueType32)
    //   convertDPDtoBID(ValueType64)
    //   convertDPDtoBID(ValueType128)
    // ------------------------------------------------------------------------
    if (verbose) cout << endl
                      << "TESTING CONVERSION FROM DENSELY PACKED" << endl
                      << "======================================" << endl;


    // Test that with any of a set of exponents, we can convert 32-bit
    // values correctly to DPD.

    {
        Util::ValueType32 testDecimal;
        DS::       Type32 witnessDPD;
        Util::ValueType32 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw32(0, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw32(7, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw32(52, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertDPDtoBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertDPDtoBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw32(mantissa,
                                                         exponent);

                    witnessDPD = Util::convertBIDtoDPD(testDecimal);
                    witness = Util::convertDPDtoBID(witnessDPD);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType32 specialWitness;

        testDecimal    = Util::parse32("NaN");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse32("+Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse32("-Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 64-bit
    // values correctly to DPD.

    {
        Util::ValueType64 testDecimal;
        DS::       Type64 witnessDPD;
        Util::ValueType64 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw64(0, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw64(7, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw64(52, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertDPDtoBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertDPDtoBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw64(mantissa,
                                                         exponent);

                    witnessDPD = Util::convertBIDtoDPD(testDecimal);
                    witness = Util::convertDPDtoBID(witnessDPD);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType64 specialWitness;

        testDecimal    = Util::parse64("NaN");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse64("+Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse64("-Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }

    // Test that with any of a set of exponents, we can convert 128-bit
    // values correctly to DPD.

    {
        Util::ValueType128 testDecimal;
        DS::       Type128 witnessDPD;
        Util::ValueType128 witness;

                    // 0e0

        testDecimal = Util::makeDecimalRaw128(0, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 7e0

        testDecimal = Util::makeDecimalRaw128(7, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // 52e0

        testDecimal = Util::makeDecimalRaw128(52, 0);
        witnessDPD  = Util::convertBIDtoDPD(testDecimal);
        witness     = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!bsl::memcmp(&testDecimal, &witness, sizeof(witness)));

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                         cout << "convertDPDtoBID, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                         cout << "convertDPDtoBID, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101) {

                    int mantissa = static_cast<int>(t_mantissa);

                    testDecimal = Util::makeDecimalRaw128(mantissa,
                                                         exponent);

                    witnessDPD = Util::convertBIDtoDPD(testDecimal);
                    witness = Util::convertDPDtoBID(witnessDPD);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testDecimal,
                                              &witness,
                                               sizeof(witness)));
                }
            }
        }

        Util::ValueType128 specialWitness;

        testDecimal    = Util::parse128("NaN");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse128("+Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse128("-Inf");
        witnessDPD     = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(witnessDPD);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }
}

void TestDriver::testCase19()
{
    // ------------------------------------------------------------------------
    // TESTING CONVERSION TO DENSELY PACKED
    //
    // Concerns:
    //:  1 Values in the implementation format are represented faithfully and
    //:    correctly in the DPD format, when converted.
    //:
    //:  2 The value, after conversion, has the same cohort as the original
    //:    value.
    //:
    //:  3 32, 64, and 128 bit variations all work correctly.
    //:
    //:  4 Special cases, such as Infinity and NaN are represented correctly as
    //:    DPD.
    //
    // Plan:
    //:  1 Iterate through a set of test mantissa and convert them to DPD,
    //:    comparing the result to a canonically constructed value in DPD.
    //:    (C-1..3)
    //:
    //:  2 Test the special case values explicitly, by converting to DPD, then
    //:    using the conversion back.  Check that the properties of these
    //:    special cases hold. (C-3,4)
    //
    // Testing
    //   convertBIDtoDPD(ValueType32)
    //   convertBIDtoDPD(ValueType64)
    //   convertBIDtoDPD(ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING CONVERSION TO DENSELY PACKED" << endl
                      << "====================================" << endl;

    // Test that with any of a set of exponents, we can convert 32-bit
    // values correctly to DPD.

    {
        Util::ValueType32 testDecimal;
        DS::       Type32 testConvert;

                    // 0e0
        {
            const unsigned int witness = 0x22500000;
            testDecimal = Util::makeDecimalRaw32(0, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);
            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

                    // 7e0
        {
            const unsigned int witness = 0x22500007;
            testDecimal = Util::makeDecimalRaw32(7, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);
            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

                    // 52e0
        {
            const unsigned int witness = 0x22500052;
            testDecimal = Util::makeDecimalRaw32(52, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);
            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertBIDtoDPD, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertBIDtoDPD, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int t_mantissa = mantissas[t_m];
                          int   exponent = exponents[t_e];

                if (t_mantissa <= 9999999 && t_mantissa >= -9999999
                 &&   exponent <= 90      &&   exponent >= -101)
                {
                    int mantissa = static_cast<int>(t_mantissa);

                    bsl::string parseString = makeParseString(mantissa,
                                                              exponent);

                    Util::ValueType32 parseValue = Util::parse32(
                                                          parseString.c_str());

                    DS::Type32 witness = Util::convertBIDtoDPD(parseValue);

                    testDecimal = Util::makeDecimalRaw32(mantissa, exponent);
                    testConvert = Util::convertBIDtoDPD(testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));

                }
            }
        }

        Util::ValueType32 specialWitness;

        testDecimal    = Util::parse32("NaN");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse32("+Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse32("-Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }
    // Test that with any of a set of exponents, we can convert 64-bit
    // values correctly to DPD.

    {
           Util::ValueType64 testDecimal;
           DS::       Type64 testConvert;

                    // 0e0
        {
            const unsigned long long witness = 0x2238000000000000ULL;
            testDecimal = Util::makeDecimalRaw64(0, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);
            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }
                    // 7e0
        {
            const unsigned long long witness = 0x2238000000000007ULL;
            testDecimal = Util::makeDecimalRaw64(7, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);
            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }
                    // 52e0
        {
            const unsigned long long witness = 0x2238000000000052ULL;
            testDecimal =    Util::makeDecimalRaw64(52, 0);
            testConvert =    Util::convertBIDtoDPD(testDecimal);

            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertBIDtoDPD, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertBIDtoDPD, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (mantissa <=  9999999999999999ll &&
                    mantissa >= -9999999999999999ll &&
                    exponent <= 369 && exponent >= -398)
                {
                    bsl::string parseString = makeParseString(mantissa,
                                                              exponent);

                    Util::ValueType64 parseValue = Util::parse64(
                                                          parseString.c_str());

                    DS::Type64 witness = Util::convertBIDtoDPD(parseValue);

                    testDecimal = Util::makeDecimalRaw64(mantissa, exponent);
                    testConvert = Util::convertBIDtoDPD(testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));
                }
            }
        }

        Util::ValueType64 specialWitness;

        testDecimal    = Util::parse64("NaN");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse64("+Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse64("-Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }


    // Test that with any of a set of exponents, we can convert 128-bit
    // values correctly to DPD.

    {
        Util::ValueType128 testDecimal;
        DS::       Type128 testConvert;

                    // 0e0
        {
            unsigned long long dpd[] = { 0x2208000000000000ULL,
                                         0x0000000000000000ULL };
            bdldfp::Uint128    witness(dpd[0], dpd[1]);

            testDecimal = Util::makeDecimalRaw128(0, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);

            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }
                    // 7e0
        {
            unsigned long long dpd[] = { 0x2208000000000000ULL,
                                         0x0000000000000007ULL };
            bdldfp::Uint128    witness(dpd[0], dpd[1]);

            testDecimal = Util::makeDecimalRaw128(7, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);

            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

                    // 52e0
        {
            unsigned long long dpd[] = { 0x2208000000000000ULL,
                                         0x0000000000000052ULL };
            bdldfp::Uint128    witness(dpd[0], dpd[1]);

            testDecimal = Util::makeDecimalRaw128(52, 0);
            testConvert = Util::convertBIDtoDPD(testDecimal);

            ASSERT(!bsl::memcmp(&testConvert, &witness, sizeof(testConvert)));
        }

                    // Table driven test for conversion

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose)
                           cout << "convertBIDtoDPD, mantissa num: "
                                << t_m << ", " << mantissas[t_m] << endl;

            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose)
                           cout << "convertBIDtoDPD, exponent num: "
                                << t_e << ", "
                                << exponents[t_e] << endl;

                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (exponent <= 6111 && exponent >= -6176) {

                    bsl::string parseString = makeParseString(mantissa,
                                                              exponent);

                    Util::ValueType128 parseValue = Util::parse128(
                                                          parseString.c_str());

                    DS::Type128 witness = Util::convertBIDtoDPD(parseValue);

                    testDecimal = Util::makeDecimalRaw128(mantissa, exponent);
                    testConvert = Util::convertBIDtoDPD(testDecimal);

                    LOOP4_ASSERT(t_m, t_e, mantissa, exponent,
                                 !bsl::memcmp(&testConvert,
                                              &witness,
                                               sizeof(testConvert)));
                }
            }
        }

        Util::ValueType128 specialWitness;

        testDecimal    = Util::parse128("NaN");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT(!Util::equal(testDecimal,    testDecimal));
        ASSERT(!Util::equal(specialWitness, specialWitness));

        testDecimal    = Util::parse128("+Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));

        testDecimal    = Util::parse128("-Inf");
        testConvert    = Util::convertBIDtoDPD(testDecimal);
        specialWitness = Util::convertDPDtoBID(testConvert);

        ASSERT( Util::equal(testDecimal, specialWitness));
    }
}

void TestDriver::testCase18()
{
    // --------------------------------------------------------------------
    // TESTING 'format'
    //
    // Concerns:
    //: 1 That for input decimal value including minimum, maximum and
    //    special values 'format' functions output human readable string.
    //:
    //: 2 That 'format' returns the necessary size of a buffer with no
    //:   effect on 'buffer' which is sufficient for coping resultant
    //:   string if the string size exceeds the size of the 'buffer'.
    //:
    //: 3 That 'format' returns the necessary size of a buffer sufficient
    //:   for storing the specified decimal 'value' formatted to human
    //:   readable string with no effect on the 'buffer' if the 'length' is
    //:   negative.
    //:
    //: 4 That 'format' outputs decimal value in fixed notation if
    //:   format configuration attribute 'style' is 'e_FIXED'.
    //:
    //: 5 That 'format' outputs decimal value in scientific notation if
    //:   format configuration attribute 'style' is 'e_SCIENTIFIC'.
    //:
    //: 6 That 'format' outputs decimal value in natural notation if
    //:   format configuration attribute 'style' is 'e_NATURAL'.
    //:
    //: 7 That 'format' outputs decimal value to expected human readable
    //:   string according to various combination of attributes specified
    //:   in 'cfg' object.
    //:
    //: 9 That 'format' does not write terminating null character to the
    //:   buffer.
    //:
    //: 10 That length of fraction part of the decimal value is output to
    //:    the 'buffer' equals the precision value specified in 'cfg'
    //:    object in fixed and scientific notations.
    //:
    //: 11 That if the number of digits after decimal point is less than
    //:    the specified precision then the fraction part is expanded by
    //:    by '0' on the right up to the precision length.
    //:
    //: 12 That if the number of digits after decimal pointis greater than
    //:    the specified precision then the fraction part is cut off to
    //:    fewer digits designated by the precision and rounded so that the
    //:    resultant value to be as close as possible to initial value.
    //:
    //: 13 That a special decimal value is output correctly.
    //:
    //: 14 That if format configuration attribute 'style' is 'e_NATURAL' then
    //:    'format' outputs all significant digits of the decimal value
    //:    regardless of the 'precision' attribute of the format configuration.
    //:
    //: 15 QoI: Asserted precondition violations are detected when enabled.
    //
    // Plan:
    //:
    //: 1 Using a table driven technique test that 'format' returns the
    //:   necessary size of a buffer with no effect on 'buffer' which is
    //:   sufficient for coping resultant string if the string size exceeds
    //:   the size of 'buffer'.  (C-2,3)
    //:
    //:  1 For each test element in the table specify decimal value,
    //:    configuration, pointer to the buffer, size of the buffer and
    //:    expected length.
    //:
    //:  2 For each test element create a 'Decimal32' object.
    //:
    //:  3 Fill in the buffer with 'x' character.
    //:
    //:  4 Call 'format' function for the decimal object created in P-1.2.
    //:    Test that the buffer was not modified and resultant value
    //:    equals to the expected value.
    //:
    //: 2 Using a loop-based technique test that 'format' function produces
    //:   a human readable string for different valid decimal numbers
    //:   designated by the significand value consisting of various number
    //:   of digits and the exponent in the range of minimum to maximum
    //:   exponent value defined by 'Decimal32' type.  For the test purpose
    //:   use configuration object with precision value set to 100.  (C-1)
    //:
    //:  1 Create a 'Decimal32' object.
    //:
    //:  2 Call 'format' function for the value created in P-2.1.
    //:
    //:  3 Parse the string obtained in P-2.2 and ensure that the resultant
    //:    value equals to the value created in P-2.1.
    //:
    //:  4 Repeat P-2.1..3 for 'e_FIXED', 'e_SCIENTIFIC' and 'e_NATURAL'
    //:    format notations.
    //:
    //: 3 Using a table driven technique test that 'format' function
    //:   produces a human readable string from a decimal number with the
    //:   various combination of configuration attributes.
    //:
    //:  1 For each test element in the table specify decimal value,
    //:    'precision', 'style', 'sign', 'decimalPoint' and expected
    //:    resultant string.
    //:
    //:  2 For each test element create a 'Decimal32' object.
    //:
    //:  3 Fill in output 'buffer' with 'x' character.
    //:
    //:  4 Call 'format' function for the decimal object created in P-3.2.
    //:    Test that the 'buffer' is filled in by a string that equals
    //:    to the expected string and length of the resultant value equals
    //:    to length of the expected string.
    //:
    //:  5 Test that if rounding is required the 'format' function rounds
    //:    up the decimal value as "round-half-up".  (C-12)
    //:
    //:  6 Test that a character in the 'buffer' that follows by a
    //:    character representing the less significant digit equals to 'x'.
    //:    (C-9)
    //:
    //:  7 Test that for normal decimal values length of string
    //:    representing fraction part of equals to the specified precision.
    //:    (C-10)
    //:
    //: 4 Repeat P1-3 for Decimal64 and Decimal128 types.
    //
    // Testing:
    //   int format(char *, int, ValueType32,  const DecimalFormatConfig&);
    //   int format(char *, int, ValueType64,  const DecimalFormatConfig&);
    //   int format(char *, int, ValueType128, const DecimalFormatConfig&);
    // --------------------------------------------------------------------

#define F(PRECISION) Config(PRECISION, Config::e_FIXED)
#define S(PRECISION) Config(PRECISION, Config::e_SCIENTIFIC)
#define N(PRECISION) Config(PRECISION, Config::e_NATURAL)

    if (verbose) cout << endl
                      << "TEST FORMAT METHODS" << endl
                      << "===================" << endl;

    if (verbose) cout << endl
                      << "Test ValueType32" << endl
                      << "----------------" << endl;

#define DEC(X) Util::parse32(#X)
    //-----------------------------------------------------------------
    // C-2,3
    {
        typedef Util::ValueType32 Type;

        const Type SUBN_P  = Util::denormMin32();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity32();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN32();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN32();
        const Type NAN_S_N = Util::negate(NAN_S_P);

        const int  k_BUFFER_SIZE = 256;
        char       BUFFER[k_BUFFER_SIZE];
        char      *B_PTR = &BUFFER[0];

        static const struct {
            const int     d_line;
            const Type    d_decimal;
            const Config  d_config;
            char         *d_buffer;
            const int     d_bufferSize;
            const int     d_expected;
        } DATA [] = {
            //------------------------------------------------------------
            // Line | Decimal      | Config | Buffer | Buffer | Expected
            //      |              |        |        | Size   | Length
            //------------------------------------------------------------
            {  L_,   DEC( 1234.865),    F(3),   B_PTR,       0,       8 },
            {  L_,   DEC(-1234.865),    F(3),   B_PTR,      -1,       9 },
            {  L_,   DEC( 1234.865),    F(3),       0,      -1,       8 },
            {  L_,   SUBN_P,            F(0),   B_PTR,       0,       1 },
            {  L_,   SUBN_N,            F(0),   B_PTR,       0,       2 },
            {  L_,   INF_P,             F(0),   B_PTR,       0,       3 },
            {  L_,   INF_N,             F(0),   B_PTR,       0,       4 },
            {  L_,   NAN_Q_P,           F(0),   B_PTR,       0,       3 },
            {  L_,   NAN_Q_N,           F(0),   B_PTR,       0,       4 },
            {  L_,   NAN_S_P,           F(0),   B_PTR,       0,       4 },
            {  L_,   NAN_S_N,           F(0),   B_PTR,       0,       5 },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(B_PTR, k_BUFFER_SIZE, 'x');

            const int     LINE        = DATA[ti].d_line;
            const Type    DECIMAL32   = DATA[ti].d_decimal;
            const Config  CONFIG      = DATA[ti].d_config;
            char         *BUFFER      = DATA[ti].d_buffer;
            const int     BUFFER_SIZE = DATA[ti].d_bufferSize;
            const int     EXPECTED    = DATA[ti].d_expected;

            int len = Util::format(BUFFER,
                                   BUFFER_SIZE,
                                   DECIMAL32,
                                   CONFIG);

            LOOP3_ASSERT(LINE, len, EXPECTED, len == EXPECTED);
            ASSERTV(L_, B_PTR == bsl::search_n(B_PTR,
                                               B_PTR + k_BUFFER_SIZE,
                                               k_BUFFER_SIZE,
                                               'x'));
        }
    }

    {
        if (verbose) cout << "Loop-based test" << endl;

        typedef Util::ValueType32 Type;

        const int SIGNIFICANDS[] = {       1,
                                          22,
                                         333,
                                        4444,
                                       55555,
                                      666666,
                                     7777777,
        };
        const int NUM_SIGNIFCANDS = static_cast<int>(sizeof SIGNIFICANDS
                                                   / sizeof *SIGNIFICANDS);

        const Config CONFIGURATIONS[] = { F(101),
                                          S(7),
                                          N(0),
        };

        const int NUM_CONFIGURATIONS = static_cast<int>(
                                                 sizeof CONFIGURATIONS
                                                 / sizeof *CONFIGURATIONS);

        const int   BUFFER_SIZE = 256;
        char        BUFFER[BUFFER_SIZE];
        for (int ci = 0; ci < NUM_CONFIGURATIONS; ++ci) {

            const Config& CONFIG       = CONFIGURATIONS[ci];
            const int     EXPONENT_MIN = -101;
            const int     EXPONENT_MAX =   90;

            for (int si = 0; si < NUM_SIGNIFCANDS; ++si) {
                const int SIGNIFICAND = SIGNIFICANDS[si];

                for (int ei = EXPONENT_MIN; ei <= EXPONENT_MAX; ++ei) {
                    const int  EXPONENT = ei;
                    Type VALUE = static_cast<Type>(Util::makeDecimalRaw32(
                                                                   SIGNIFICAND,
                                                                   EXPONENT));
                    const Type EXPECTED = VALUE;

                    int len = Util::format(BUFFER,
                                           BUFFER_SIZE,
                                           VALUE,
                                           CONFIG);

                    const Type RESULT =
                          Util::parse32(bsl::string(BUFFER, len, pa).c_str());
                    LOOP3_ASSERT(L_,
                                 SIGNIFICAND,
                                 EXPONENT,
                                 Util::equal(RESULT, EXPECTED));
                }
            }
        }
    }
    {
        if (verbose) cout << "Table-driven test" << endl;

        typedef Util::ValueType32 Type;

        const Type SUBN_P  = Util::denormMin32();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity32();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN32();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN32();
        const Type NAN_S_N = Util::negate(NAN_S_P);
        const Type MAX_P   = Util::max32();
        const Type MAX_N   = Util::negate(MAX_P);
        const Type MIN_P   = Util::min32();
        const Type MIN_N   = Util::negate(MIN_P);

        static const struct {
            const int          d_line;
            const Type         d_decimal;
            const Config       d_config;
            const char        *d_expected;
        } DATA [] = {
            //-----------------------------------------------------
            // Line | Decimal   | Configuration |  Expected
            //-----------------------------------------------------
            // ----------------------------------------------------
            // FIXED format
            // C-1,4
            {  L_,    SUBN_P,           F(101),     SUBNORMAL_DECIMAL_32 },
            {  L_,    SUBN_N,           F(101), "-" SUBNORMAL_DECIMAL_32 },
            {  L_,    INF_P,            F(0),     "inf"                  },
            {  L_,    INF_N,            F(0),    "-inf"                  },
            {  L_,    NAN_Q_P,          F(0),     "nan"                  },
            {  L_,    NAN_Q_N,          F(0),    "-nan"                  },
            {  L_,    NAN_S_P,          F(0),     "snan"                 },
            {  L_,    NAN_S_N,          F(0),    "-snan"                 },
            {  L_,    MAX_P,            F(0),      MAX_DECIMAL_32        },
            {  L_,    MAX_N,            F(0),  "-" MAX_DECIMAL_32        },
            {  L_,    MIN_P,            F(95),     MIN_DECIMAL_32        },
            {  L_,    MIN_N,            F(95), "-" MIN_DECIMAL_32        },
            {  L_,    DEC(-0.0),        F(0),    "-0"                    },
            {  L_,    DEC(0.0),         F(0),     "0"                    },
            {  L_,    DEC(0.0),         F(1),     "0.0"                  },
            {  L_,    DEC(0.00),        F(2),     "0.00"                 },
            {  L_,    DEC(0.000),       F(3),     "0.000"                },
            {  L_,    DEC(0.0),         F(4),     "0.0000"               },
            {  L_,    DEC(0.00),        F(5),     "0.00000"              },
            {  L_,    DEC(0.000),       F(6),     "0.000000"             },
            {  L_,    DEC(123.0),       F(0),     "123"                  },
            {  L_,    DEC(1230e-1),     F(0),     "123"                  },
            // -----------------------------------------------------------
            // SCIENTIFIC format
            // C-1,5
            {  L_,    SUBN_P,            S(0),    "1e-101"       },
            {  L_,    SUBN_N,            S(0),   "-1e-101"       },
            {  L_,    INF_P,             S(0),    "inf"          },
            {  L_,    INF_N,             S(0),   "-inf"          },
            {  L_,    NAN_Q_P,           S(0),    "nan"          },
            {  L_,    NAN_Q_N,           S(0),   "-nan"          },
            {  L_,    NAN_S_P,           S(0),    "snan"         },
            {  L_,    NAN_S_N,           S(0),   "-snan"         },
            {  L_,    MAX_P,             S(6),    "9.999999e+96" },
            {  L_,    MAX_N,             S(6),   "-9.999999e+96" },
            {  L_,    MAX_P,             S(0),    "1e+97"        },
            {  L_,    MAX_N,             S(0),   "-1e+97"        },
            {  L_,    MAX_P,             S(1),    "1.0e+97"      },
            {  L_,    MAX_N,             S(1),   "-1.0e+97"      },
            {  L_,    MIN_P,             S(0),    "1e-95"        },
            {  L_,    MIN_N,             S(0),   "-1e-95"        },
            {  L_,    DEC(-0.0),         S(0),   "-0e+00"        },
            {  L_,    DEC(0.0),          S(0),    "0e+00"        },
            {  L_,    DEC(0.0),          S(1),    "0.0e+00"      },
            {  L_,    DEC(0.00),         S(2),    "0.00e+00"     },
            {  L_,    DEC(0.000),        S(3),    "0.000e+00"    },
            {  L_,    DEC(123.0),        S(2),    "1.23e+02"     },
            {  L_,    DEC(1230e-1),      S(2),    "1.23e+02"     },
            {  L_,    DEC(1230e-1),      S(3),    "1.230e+02"    },
            //-------------------------------------------------------------
            // NATURAL format
            // C-6,14
            {  L_,    DEC(0.0),          N(0),     "0.0"            },
            {  L_,    DEC(0.00),         N(0),     "0.00"           },
            {  L_,    DEC(0.000),        N(0),     "0.000"          },
            {  L_,    DEC(0.0000),       N(0),     "0.0000"         },
            {  L_,    DEC(0.00000),      N(0),     "0.00000"        },
            {  L_,    DEC(0.000000),     N(0),     "0.000000"       },
            {  L_,    DEC(0.0000000),    N(0),     "0e-07"          },
            {  L_,    DEC(0.00000000),   N(0),     "0e-08"          },

            {  L_,    DEC(1E-8),         N(0),     "1e-08"          },
            {  L_,    DEC(1E-7),         N(0),     "1e-07"          },
            {  L_,    DEC(1E-6),         N(0),     "0.000001"       },
            {  L_,    DEC(1E-5),         N(0),     "0.00001"        },
            {  L_,    DEC(1E-4),         N(0),     "0.0001"         },

            {  L_,    DEC(1E-8),         N(0),     "1e-08"          },
            {  L_,    DEC(11E-8),        N(0),     "1.1e-07"        },
            {  L_,    DEC(111E-8),       N(0),     "0.00000111"     },
            {  L_,    DEC(1111E-8),      N(0),     "0.00001111"     },
            {  L_,    DEC(11111E-8),     N(0),     "0.00011111"     },

            {  L_,    DEC(1234567E+2),   N(0),     "1.234567e+08"   },
            {  L_,    DEC(1234567E+1),   N(1),     "1.234567e+07"   },
            {  L_,    DEC(1234567E-0),   N(2),     "1234567"        },
            {  L_,    DEC(1234567E-1),   N(3),     "123456.7"       },
            {  L_,    DEC(1234567E-2),   N(4),     "12345.67"       },
            {  L_,    DEC(1234567E-3),   N(5),     "1234.567"       },
            {  L_,    DEC(1234567E-4),   N(6),     "123.4567"       },
            {  L_,    DEC(1234567E-5),   N(7),     "12.34567"       },
            {  L_,    DEC(1234567E-6),   N(8),     "1.234567"       },
            {  L_,    DEC(1234567E-7),   N(9),     "0.1234567"      },
            {  L_,    DEC(1234567E-8),   N(8),     "0.01234567"     },
            {  L_,    DEC(1234567E-9),   N(7),     "0.001234567"    },
            {  L_,    DEC(1234567E-10),  N(6),     "0.0001234567"   },
            {  L_,    DEC(1234567E-11),  N(5),     "0.00001234567"  },
            {  L_,    DEC(1234567E-12),  N(4),     "0.000001234567" },
            {  L_,    DEC(1234567E-13),  N(3),     "1.234567e-07"   },
            {  L_,    DEC(1234567E-14),  N(2),     "1.234567e-08"   },

            //-------------------------------------------------------------
            // C-7
            //-------------------------------------------------------------
            // Test 'sign' attribute
#define CONFIG(SIGN) Config(0,                  \
                            Config::e_FIXED,    \
                            Config::SIGN)

            {  L_,    DEC( 123.0),    CONFIG(e_NEGATIVE_ONLY),  "123" },
            {  L_,    DEC(-123.0),    CONFIG(e_NEGATIVE_ONLY), "-123" },
            {  L_,    DEC( 123.0),    CONFIG(e_ALWAYS),        "+123" },
            {  L_,    DEC(-123.0),    CONFIG(e_ALWAYS),        "-123" },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'infinity' attribute
#define CONFIG(INF) Config(0,                       \
                           Config::e_SCIENTIFIC,    \
                           Config::e_NEGATIVE_ONLY, \
                           INF)

            {  L_,    INF_P,          CONFIG(""),         ""          },
            {  L_,    INF_P,          CONFIG("inf"),      "inf"       },
            {  L_,    INF_N,          CONFIG("Inf"),     "-Inf"       },
            {  L_,    INF_N,          CONFIG("INF"),     "-INF"       },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'nan' attribute
#define CONFIG(NAN) Config(0,                                   \
                           Config::e_SCIENTIFIC,                \
                           Config::e_NEGATIVE_ONLY,             \
                           "",                                  \
                           NAN)

            {  L_,    NAN_Q_P,        CONFIG(""),         ""          },
            {  L_,    NAN_Q_P,        CONFIG("nan"),      "nan"       },
            {  L_,    NAN_Q_N,        CONFIG("NaN"),     "-NaN"       },
            {  L_,    NAN_Q_N,        CONFIG("NAN"),     "-NAN"       },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'snan' attribute
#define CONFIG(SNAN) Config(0,                                          \
                            Config::e_SCIENTIFIC,                       \
                            Config::e_NEGATIVE_ONLY,                    \
                            "",                                         \
                            "",                                         \
                            SNAN)

             {  L_,    NAN_S_P,       CONFIG(""),          ""       },
             {  L_,    NAN_S_P,       CONFIG("snan"),      "snan"   },
             {  L_,    NAN_S_N,       CONFIG("sNaN"),     "-sNaN"   },
             {  L_,    NAN_S_N,       CONFIG("sNAN"),     "-sNAN"   },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'point'
#define CONFIG(POINT) Config(2,                         \
                             Config::e_SCIENTIFIC,      \
                             Config::e_NEGATIVE_ONLY,   \
                             "",                        \
                             "",                        \
                             "",                        \
                             POINT)

            {  L_,    DEC( 123.0),    CONFIG('.'),     "1.23e+02"     },
            {  L_,    DEC(-123.0),    CONFIG(','),    "-1,23e+02"     },
            {  L_,    DEC( 123.0),    CONFIG('_'),     "1_23e+02"     },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'exponent'
#define CONFIG(EXP) Config(2,                           \
                           Config::e_SCIENTIFIC,        \
                           Config::e_ALWAYS,            \
                           "",                          \
                           "",                          \
                           "",                          \
                           '.',                         \
                           EXP)

            {  L_,    DEC(-123.0),    CONFIG('E'),     "-1.23E+02"   },
            {  L_,    DEC( 123.0),    CONFIG('e'),     "+1.23e+02"   },
            {  L_,    DEC(-123.0),    CONFIG('^'),     "-1.23^+02"   },
#undef CONFIG
            //-------------------------------------------------------------
            // C-11
            {  L_,    DEC(1.11),         F(2),      "1.11"       },
            {  L_,    DEC(1.11),         F(3),      "1.110"      },
            {  L_,    DEC(1.11),         F(4),      "1.1100"     },
            {  L_,    DEC(1.11),         S(2),      "1.11e+00"   },
            {  L_,    DEC(1.11),         S(3),      "1.110e+00"  },
            {  L_,    DEC(1.11),         S(4),      "1.1100e+00" },
            //-------------------------------------------------------------
            // C-12
            {  L_,    DEC(4.44),         F(2),      "4.44"       },
            {  L_,    DEC(4.44),         F(1),      "4.4"        },
            {  L_,    DEC(4.44),         F(0),      "4"          },
            {  L_,    DEC(5.55),         F(2),      "5.55"       },
            {  L_,    DEC(5.55),         F(1),      "5.6"        },
            {  L_,    DEC(5.55),         F(0),      "6"          },
            {  L_,    DEC(9.99),         F(2),      "9.99"       },
            {  L_,    DEC(9.99),         F(1),      "10.0"       },
            {  L_,    DEC(9.99),         F(0),      "10"         },
            {  L_,    DEC(4.44),         S(2),      "4.44e+00"   },
            {  L_,    DEC(4.44),         S(1),      "4.4e+00"    },
            {  L_,    DEC(4.44),         S(0),      "4e+00"      },
            {  L_,    DEC(5.55),         S(2),      "5.55e+00"   },
            {  L_,    DEC(5.55),         S(1),      "5.6e+00"    },
            {  L_,    DEC(5.55),         S(0),      "6e+00"      },
            {  L_,    DEC(9.99),         S(2),      "9.99e+00"   },
            {  L_,    DEC(9.99),         S(1),      "1.0e+01"    },
            {  L_,    DEC(9.99),         S(0),      "1e+01"      },
            //-------------------------------------------------------------
            // C-13
            {  L_,    INF_P,             F(2),      "inf"        },
            {  L_,    INF_N,             F(3),     "-inf"        },
            {  L_,    NAN_Q_P,           F(4),      "nan"        },
            {  L_,    NAN_Q_N,           F(5),     "-nan"        },
            {  L_,    NAN_S_P,           F(6),      "snan"       },
            {  L_,    NAN_S_N,           F(7),     "-snan"       },

            {  L_,    INF_P,             S(5),      "inf"        },
            {  L_,    INF_N,             S(4),     "-inf"        },
            {  L_,    NAN_Q_P,           S(3),      "nan"        },
            {  L_,    NAN_Q_N,           S(2),     "-nan"        },
            {  L_,    NAN_S_P,           S(1),      "snan"       },
            {  L_,    NAN_S_N,           S(0),     "-snan"       },

            {  L_,    INF_P,             N(0),     "inf"         },
            {  L_,    INF_N,             N(0),    "-inf"         },
            {  L_,    NAN_Q_P,           N(0),     "nan"         },
            {  L_,    NAN_Q_N,           N(0),    "-nan"         },
            {  L_,    NAN_S_P,           N(0),     "snan"        },
            {  L_,    NAN_S_N,           N(0),    "-snan"        },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        const int k_BUFFER_SIZE = 256;
        char      buffer[k_BUFFER_SIZE];

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(&buffer[0], k_BUFFER_SIZE, 'x');

            const int          LINE        = DATA[ti].d_line;
            const Type         DECIMAL32   = DATA[ti].d_decimal;
            const Config       CONFIG      = DATA[ti].d_config;
            const bsl::string  EXPECTED(DATA[ti].d_expected, pa);

            int len = Util::format(buffer,
                                   k_BUFFER_SIZE,
                                   DECIMAL32,
                                   CONFIG);

            const bsl::string RESULT(buffer, len, pa);
            if (veryVerbose) { P_(len) P(RESULT); }

            ASSERTV(LINE, len, len >= 0);
            LOOP3_ASSERT(LINE, RESULT, EXPECTED, RESULT == EXPECTED);
            LOOP3_ASSERT(LINE,
                         len,
                         EXPECTED.length(),
                         len == static_cast<int>(EXPECTED.length()));

            //-------------------------------------------------------------
            // C-9
            LOOP2_ASSERT(LINE, buffer[len], 'x' == buffer[len]);

            //-------------------------------------------------------------
            // C-10
            if (FP_NORMAL == Util::classify(DECIMAL32) &&
                Config::e_NATURAL != CONFIG.style())
            {
                const char *BEGIN     = &buffer[0];
                const char *END       = &buffer[len];
                const char *POINT_POS = bsl::find(BEGIN,
                                                  END,
                                                  CONFIG.decimalPoint());
                if (POINT_POS == END) {
                    LOOP2_ASSERT(LINE,
                                 CONFIG.precision(),
                                 0 == CONFIG.precision());
                }
                else {
                    const char *EXPONENT_POS = bsl::find(
                                                        POINT_POS,
                                                        END,
                                                        CONFIG.exponent());
                    LOOP3_ASSERT(LINE,
                                 CONFIG.precision(),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS)
                                 == CONFIG.precision());
                }
            }
        }
        if (veryVerbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            if (veryVerbose) cout << "\t'buffer == NULL'" << endl;
            {
                const int    k_SIZE = 1000;
                char         BUFFER[k_SIZE];
                const Type   V = Util::makeDecimalRaw32(0, 0);
                const Config CFG(6);

                ASSERT_PASS(Util::format(BUFFER, k_SIZE, V, CFG));
                ASSERT_FAIL(Util::format(     0, k_SIZE, V, CFG));
            }
        }
    }
#undef DEC

    if (verbose) cout << endl
                      << "Test ValueType64" << endl
                      << "----------------" << endl;
#define DEC(X) Util::parse64(#X)
    //-----------------------------------------------------------------
    // C-2,3
    {
        typedef Util::ValueType64 Type;

        const Type SUBN_P  = Util::denormMin64();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity64();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN64();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN64();
        const Type NAN_S_N = Util::negate(NAN_S_P);

        const int  k_BUFFER_SIZE = 256;
        char       BUFFER[k_BUFFER_SIZE];
        char      *B_PTR = &BUFFER[0];

        static const struct {
            const int     d_line;
            const Type    d_decimal;
            const Config  d_config;
            char         *d_buffer;
            const int     d_bufferSize;
            const int     d_expected;
        } DATA [] = {
        //------------------------------------------------------------
        // Line | Decimal      | Config | Buffer | Buffer | Expected
        //      |              |        |        | Size   | Length
        //------------------------------------------------------------
        {  L_,   DEC( 1234.865),    F(3),   B_PTR,       0,       8 },
        {  L_,   DEC(-1234.865),    F(3),   B_PTR,      -1,       9 },
        {  L_,   DEC( 1234.865),    F(3),       0,      -1,       8 },
        {  L_,   DEC( 1234.865),    S(6),   B_PTR,       0,      12 },
        {  L_,   DEC(-1234.865),    S(6),   B_PTR,      -1,      13 },
        {  L_,   DEC( 1234.865),    S(6),       0,      -1,      12 },

        {  L_,   SUBN_P,            F(0),   B_PTR,       0,       1 },
        {  L_,   SUBN_N,            F(0),   B_PTR,       0,       2 },
        {  L_,   INF_P,             F(0),   B_PTR,       0,       3 },
        {  L_,   INF_N,             F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_Q_P,           F(0),   B_PTR,       0,       3 },
        {  L_,   NAN_Q_N,           F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_S_P,           F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_S_N,           F(0),   B_PTR,       0,       5 },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(B_PTR, k_BUFFER_SIZE, 'x');

            const int     LINE        = DATA[ti].d_line;
            const Type    DECIMAL     = DATA[ti].d_decimal;
            const Config  CONFIG      = DATA[ti].d_config;
            char         *BUFFER      = DATA[ti].d_buffer;
            const int     BUFFER_SIZE = DATA[ti].d_bufferSize;
            const int     EXPECTED    = DATA[ti].d_expected;

            int len = Util::format(BUFFER,
                                   BUFFER_SIZE,
                                   DECIMAL,
                                   CONFIG);

            LOOP3_ASSERT(LINE, len, EXPECTED, len == EXPECTED);
            ASSERTV(L_, B_PTR == bsl::search_n(B_PTR,
                                               B_PTR + k_BUFFER_SIZE,
                                               k_BUFFER_SIZE,
                                               'x'));
        }
    }
    {
        if (verbose) cout << "Loop-based test" << endl;

        typedef Util::ValueType64 Type;

        const unsigned long long SIGNIFICANDS[] = {       1ull,
                                                         22ull,
                                                        333ull,
                                                       4444ull,
                                                      55555ull,
                                                     666666ull,
                                                    7777777ull,
                                                   88888888ull,
                                                  999999999ull,
                                                 1111111111ull,
                                                22222222222ull,
                                               333333333333ull,
                                              4444444444444ull,
                                             55555555555555ull,
                                            666666666666666ull,
                                           7777777777777777ull,
        };
        const int NUM_SIGNIFCANDS = static_cast<int>(
                                                   sizeof SIGNIFICANDS
                                                   / sizeof *SIGNIFICANDS);

        const Config CONFIGURATIONS[] = { F(398),
                                          S(15),
                                          N(21),
        };

        const int NUM_CONFIGURATIONS = static_cast<int>(
                                                 sizeof CONFIGURATIONS
                                                 / sizeof *CONFIGURATIONS);

        const int BUFFER_SIZE = 1024;
        char      BUFFER[BUFFER_SIZE];

        for (int ci = 0; ci < NUM_CONFIGURATIONS; ++ci) {

            const Config& CONFIG       =  CONFIGURATIONS[ci];
            const int     EXPONENT_MIN = -398;
            const int     EXPONENT_MAX =  369;

            for (int si = 0; si < NUM_SIGNIFCANDS; ++si) {
                const unsigned long long SIGNIFICAND = SIGNIFICANDS[si];

                for (int ei = EXPONENT_MIN; ei <= EXPONENT_MAX; ++ei) {
                    const int EXPONENT = ei;
                    Type VALUE = static_cast<Type>(Util::makeDecimalRaw64(
                                                                   SIGNIFICAND,
                                                                   EXPONENT));
                    const Type EXPECTED = VALUE;

                    int len = Util::format(BUFFER,
                                           BUFFER_SIZE,
                                           VALUE,
                                           CONFIG);

                    const Type RESULT =
                          Util::parse64(bsl::string(BUFFER, len, pa).c_str());
                    LOOP3_ASSERT(L_,
                                 SIGNIFICAND,
                                 EXPONENT,
                                 Util::equal(RESULT, EXPECTED));
                }
            }
        }
    }
    {
        if (verbose) cout << "Table-driven test" << endl;

        typedef Util::ValueType64 Type;

        const Type SUBN_P  = Util::denormMin64();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity64();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN64();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN64();
        const Type NAN_S_N = Util::negate(NAN_S_P);
        const Type MAX_P   = Util::max64();
        const Type MAX_N   = Util::negate(MAX_P);
        const Type MIN_P   = Util::min64();
        const Type MIN_N   = Util::negate(MIN_P);

        static const struct {
            const int          d_line;
            const Type         d_decimal;
            const Config       d_config;
            const char        *d_expected;
        } DATA [] = {
            //-----------------------------------------------------
            // Line | Decimal   | Configuration |  Expected
            //-----------------------------------------------------

            //-----------------------------------------------------
            // FIXED format
            // C-1,4
            {  L_,    SUBN_P,           F(398),     SUBNORMAL_DECIMAL_64 },
            {  L_,    SUBN_N,           F(398), "-" SUBNORMAL_DECIMAL_64 },
            {  L_,    INF_P,            F(0),      "inf"                 },
            {  L_,    INF_N,            F(0),     "-inf"                 },
            {  L_,    NAN_Q_P,          F(0),      "nan"                 },
            {  L_,    NAN_Q_N,          F(0),     "-nan"                 },
            {  L_,    NAN_S_P,          F(0),      "snan"                },
            {  L_,    NAN_S_N,          F(0),     "-snan"                },
            {  L_,    MAX_P,            F(0),       MAX_DECIMAL_64       },
            {  L_,    MAX_N,            F(0),   "-" MAX_DECIMAL_64       },
            {  L_,    MIN_P,            F(383),     MIN_DECIMAL_64       },
            {  L_,    MIN_N,            F(383), "-" MIN_DECIMAL_64       },
            {  L_,    DEC(-0.0),        F(0),     "-0"                   },
            {  L_,    DEC(0.0),         F(0),      "0"                   },
            //------------------------------------------------------------
            // SCIENTIFIC format
            // C-1,5
            {  L_,    SUBN_P,          S(0),    "1e-398"                 },
            {  L_,    SUBN_N,          S(0),   "-1e-398"                 },
            {  L_,    INF_P,           S(0),    "inf"                    },
            {  L_,    INF_N,           S(0),   "-inf"                    },
            {  L_,    NAN_Q_P,         S(0),    "nan"                    },
            {  L_,    NAN_Q_N,         S(0),   "-nan"                    },
            {  L_,    NAN_S_P,         S(0),    "snan"                   },
            {  L_,    NAN_S_N,         S(0),   "-snan"                   },
            {  L_,    MAX_P,           S(15),   "9.999999999999999e+384" },
            {  L_,    MAX_N,           S(15),  "-9.999999999999999e+384" },
            {  L_,    MAX_P,           S(0),    "1e+385"                 },
            {  L_,    MAX_N,           S(0),   "-1e+385"                 },
            {  L_,    MAX_P,           S(1),    "1.0e+385"               },
            {  L_,    MAX_N,           S(1),   "-1.0e+385"               },
            {  L_,    MIN_P,           S(0),    "1e-383"                 },
            {  L_,    MIN_N,           S(0),   "-1e-383"                 },
            {  L_,    DEC(-0.0),       S(0),   "-0e+00"                  },
            {  L_,    DEC(0.0),        S(0),    "0e+00"                  },
            {  L_,    DEC(0.0),        S(1),    "0.0e+00"                },
            {  L_,    DEC(0.00),       S(2),    "0.00e+00"               },
            {  L_,    DEC(0.000),      S(3),    "0.000e+00"              },
            //-------------------------------------------------------------
            // NATURAL format
            // C-6,14
            {  L_,    DEC(1E-8),         N(0),     "1e-08"          },
            {  L_,    DEC(1E-7),         N(0),     "1e-07"          },
            {  L_,    DEC(1E-6),         N(0),     "0.000001"       },
            {  L_,    DEC(1E-5),         N(0),     "0.00001"        },
            {  L_,    DEC(1E-4),         N(0),     "0.0001"         },

            {  L_,    DEC(1E-8),         N(0),     "1e-08"          },
            {  L_,    DEC(11E-8),        N(0),     "1.1e-07"        },
            {  L_,    DEC(111E-8),       N(0),     "0.00000111"     },
            {  L_,    DEC(1111E-8),      N(0),     "0.00001111"     },
            {  L_,    DEC(11111E-8),     N(0),     "0.00011111"     },

            {  L_,    DEC(1234567E+2),   N(0),     "1.234567e+08"   },
            {  L_,    DEC(1234567E+1),   N(1),     "1.234567e+07"   },
            {  L_,    DEC(1234567E-0),   N(2),     "1234567"        },
            {  L_,    DEC(1234567E-1),   N(3),     "123456.7"       },
            {  L_,    DEC(1234567E-2),   N(4),     "12345.67"       },
            {  L_,    DEC(1234567E-3),   N(5),     "1234.567"       },
            {  L_,    DEC(1234567E-4),   N(6),     "123.4567"       },
            {  L_,    DEC(1234567E-5),   N(7),     "12.34567"       },
            {  L_,    DEC(1234567E-6),   N(8),     "1.234567"       },
            {  L_,    DEC(1234567E-7),   N(9),     "0.1234567"      },
            {  L_,    DEC(1234567E-8),   N(8),     "0.01234567"     },
            {  L_,    DEC(1234567E-9),   N(7),     "0.001234567"    },
            {  L_,    DEC(1234567E-10),  N(6),     "0.0001234567"   },
            {  L_,    DEC(1234567E-11),  N(5),     "0.00001234567"  },
            {  L_,    DEC(1234567E-12),  N(4),     "0.000001234567" },
            {  L_,    DEC(1234567E-13),  N(3),     "1.234567e-07"   },
            {  L_,    DEC(1234567E-14),  N(2),     "1.234567e-08"   },
            //-------------------------------------------------------------
            // C-7
            //-------------------------------------------------------------
            // Test 'sign' attribute
#define CONFIG(SIGN) Config(0,                  \
                            Config::e_FIXED,    \
                            Config::SIGN)

            {  L_,    DEC( 123.0),    CONFIG(e_NEGATIVE_ONLY),  "123" },
            {  L_,    DEC(-123.0),    CONFIG(e_NEGATIVE_ONLY), "-123" },
            {  L_,    DEC( 123.0),    CONFIG(e_ALWAYS),        "+123" },
            {  L_,    DEC(-123.0),    CONFIG(e_ALWAYS),        "-123" },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'infinity' attribute
#define CONFIG(INF) Config(0,                       \
                           Config::e_SCIENTIFIC,    \
                           Config::e_NEGATIVE_ONLY, \
                           INF)

            {  L_,    INF_P,          CONFIG(""),         ""          },
            {  L_,    INF_P,          CONFIG("inf"),      "inf"       },
            {  L_,    INF_N,          CONFIG("Inf"),     "-Inf"       },
            {  L_,    INF_N,          CONFIG("INF"),     "-INF"       },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'nan' attribute
#define CONFIG(NAN) Config(0,                                   \
                           Config::e_SCIENTIFIC,                \
                           Config::e_NEGATIVE_ONLY,             \
                           "",                                  \
                           NAN)

            {  L_,    NAN_Q_P,        CONFIG(""),         ""          },
            {  L_,    NAN_Q_P,        CONFIG("nan"),      "nan"       },
            {  L_,    NAN_Q_N,        CONFIG("NaN"),     "-NaN"       },
            {  L_,    NAN_Q_N,        CONFIG("NAN"),     "-NAN"       },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'snan' attribute
#define CONFIG(SNAN) Config(0,                                          \
                            Config::e_SCIENTIFIC,                       \
                            Config::e_NEGATIVE_ONLY,                    \
                            "",                                         \
                            "",                                         \
                            SNAN)

             {  L_,    NAN_S_P,       CONFIG(""),          ""       },
             {  L_,    NAN_S_P,       CONFIG("snan"),      "snan"   },
             {  L_,    NAN_S_N,       CONFIG("sNaN"),     "-sNaN"   },
             {  L_,    NAN_S_N,       CONFIG("sNAN"),     "-sNAN"   },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'point'
#define CONFIG(POINT) Config(2,                         \
                             Config::e_SCIENTIFIC,      \
                             Config::e_NEGATIVE_ONLY,   \
                             "",                        \
                             "",                        \
                             "",                        \
                             POINT)

            {  L_,    DEC( 123.0),    CONFIG('.'),     "1.23e+02"     },
            {  L_,    DEC(-123.0),    CONFIG(','),    "-1,23e+02"     },
            {  L_,    DEC( 123.0),    CONFIG('_'),     "1_23e+02"     },
#undef CONFIG
            //-------------------------------------------------------------
            // Test 'exponent'
#define CONFIG(EXP) Config(2,                           \
                           Config::e_SCIENTIFIC,        \
                           Config::e_ALWAYS,            \
                           "",                          \
                           "",                          \
                           "",                          \
                           '.',                         \
                           EXP)

            {  L_,    DEC(-123.0),    CONFIG('E'),     "-1.23E+02"   },
            {  L_,    DEC( 123.0),    CONFIG('e'),     "+1.23e+02"   },
            {  L_,    DEC(-123.0),    CONFIG('^'),     "-1.23^+02"   },
#undef CONFIG

            //-------------------------------------------------------------
            // C-11
            {  L_,    DEC(1.11),         F(2),      "1.11"       },
            {  L_,    DEC(1.11),         F(3),      "1.110"      },
            {  L_,    DEC(1.11),         F(4),      "1.1100"     },
            {  L_,    DEC(1.11),         S(2),      "1.11e+00"   },
            {  L_,    DEC(1.11),         S(3),      "1.110e+00"  },
            {  L_,    DEC(1.11),         S(4),      "1.1100e+00" },

            //-------------------------------------------------------------
            // C-12
            {  L_,    DEC(4.44),         F(2),      "4.44"       },
            {  L_,    DEC(4.44),         F(1),      "4.4"        },
            {  L_,    DEC(4.44),         F(0),      "4"          },
            {  L_,    DEC(5.55),         F(2),      "5.55"       },
            {  L_,    DEC(5.55),         F(1),      "5.6"        },
            {  L_,    DEC(5.55),         F(0),      "6"          },
            {  L_,    DEC(9.99),         F(2),      "9.99"       },
            {  L_,    DEC(9.99),         F(1),      "10.0"       },
            {  L_,    DEC(9.99),         F(0),      "10"         },

            {  L_,    DEC(4.44),         S(2),      "4.44e+00"   },
            {  L_,    DEC(4.44),         S(1),      "4.4e+00"    },
            {  L_,    DEC(4.44),         S(0),      "4e+00"      },
            {  L_,    DEC(5.55),         S(2),      "5.55e+00"   },
            {  L_,    DEC(5.55),         S(1),      "5.6e+00"    },
            {  L_,    DEC(5.55),         S(0),      "6e+00"      },
            {  L_,    DEC(9.99),         S(2),      "9.99e+00"   },
            {  L_,    DEC(9.99),         S(1),      "1.0e+01"    },
            {  L_,    DEC(9.99),         S(0),      "1e+01"      },

            //-------------------------------------------------------------
            // C-13
            {  L_,    INF_P,             F(2),      "inf"        },
            {  L_,    INF_N,             F(3),     "-inf"        },
            {  L_,    NAN_Q_P,           F(4),      "nan"        },
            {  L_,    NAN_Q_N,           F(5),     "-nan"        },
            {  L_,    NAN_S_P,           F(6),      "snan"       },
            {  L_,    NAN_S_N,           F(7),     "-snan"       },

            {  L_,    INF_P,             S(5),      "inf"        },
            {  L_,    INF_N,             S(4),     "-inf"        },
            {  L_,    NAN_Q_P,           S(3),      "nan"        },
            {  L_,    NAN_Q_N,           S(2),     "-nan"        },
            {  L_,    NAN_S_P,           S(1),      "snan"       },
            {  L_,    NAN_S_N,           S(0),     "-snan"       },

            {  L_,    INF_P,             N(2),     "inf"         },
            {  L_,    INF_N,             N(3),    "-inf"         },
            {  L_,    NAN_Q_P,           N(4),     "nan"         },
            {  L_,    NAN_Q_N,           N(5),    "-nan"         },
            {  L_,    NAN_S_P,           N(6),     "snan"        },
            {  L_,    NAN_S_N,           N(7),    "-snan"        },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        const int k_BUFFER_SIZE = 1024;
        char      buffer[k_BUFFER_SIZE];

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(&buffer[0], k_BUFFER_SIZE, 'x');

            const int         LINE      = DATA[ti].d_line;
            const Type        DECIMAL32 = DATA[ti].d_decimal;
            const Config      CONFIG    = DATA[ti].d_config;
            const bsl::string EXPECTED(DATA[ti].d_expected, pa);

            int len = Util::format(buffer,
                                   k_BUFFER_SIZE,
                                   DECIMAL32,
                                   CONFIG);

            const bsl::string RESULT(buffer, len, pa);
            if (veryVerbose) { P_(len) P(RESULT); }

            LOOP3_ASSERT(LINE, RESULT, EXPECTED, RESULT == EXPECTED);
            LOOP3_ASSERT(LINE,
                         len,
                         EXPECTED.length(),
                         len == static_cast<int>(EXPECTED.length()));
            //-------------------------------------------------------------
            // C-9
            LOOP2_ASSERT(LINE, buffer[len], 'x' == buffer[len]);

            //-------------------------------------------------------------
            // C-10
            if (FP_NORMAL == Util::classify(DECIMAL32) &&
                Config::e_NATURAL != CONFIG.style())
            {
                const char *BEGIN     = &buffer[0];
                const char *END       = &buffer[len];
                const char *POINT_POS = bsl::find(BEGIN,
                                                  END,
                                                  CONFIG.decimalPoint());
                if (POINT_POS == END) {
                    LOOP2_ASSERT(LINE,
                                 CONFIG.precision(),
                                 0 == CONFIG.precision());
                }
                else {
                    const char *EXPONENT_POS = bsl::find(
                                                        POINT_POS,
                                                        END,
                                                        CONFIG.exponent());
                    LOOP3_ASSERT(LINE,
                                 CONFIG.precision(),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS)
                                 == CONFIG.precision());
                }
            }
        }

        if (veryVerbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;


            if (veryVerbose) cout << "\t'buffer == NULL'" << endl;
            {
                const int    k_SIZE = 1000;
                char         BUFFER[k_SIZE];
                const Type   V = Util::makeDecimalRaw64(0, 0);
                const Config CFG(6);

                ASSERT_PASS(Util::format(BUFFER, k_SIZE, V, CFG));
                ASSERT_FAIL(Util::format(     0, k_SIZE, V, CFG));
            }
        }
    }
#undef DEC
    if (verbose) cout << endl
                      << "Test ValueType128" << endl
                      << "-----------------" << endl;

#define DEC(X) Util::parse128(#X)
    //-----------------------------------------------------------------
    // C-2,3
    {
        typedef Util::ValueType128 Type;

        const Type SUBN_P  = Util::denormMin128();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity128();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN128();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN128();
        const Type NAN_S_N = Util::negate(NAN_S_P);

        const int  k_BUFFER_SIZE = 10000;
        char       BUFFER[k_BUFFER_SIZE];
        char      *B_PTR = &BUFFER[0];

        static const struct {
            const int     d_line;
            const Type    d_decimal;
            const Config  d_config;
            char         *d_buffer;
            const int     d_bufferSize;
            const int     d_expected;
        } DATA [] = {
        //------------------------------------------------------------
        // Line | Decimal      | Config | Buffer | Buffer | Expected
        //      |              |        |        | Size   | Length
        //------------------------------------------------------------
        {  L_,   DEC( 1234.865),    F(3),   B_PTR,       0,       8 },
        {  L_,   DEC(-1234.865),    F(3),   B_PTR,      -1,       9 },
        {  L_,   DEC( 1234.865),    F(3),       0,      -1,       8 },
        {  L_,   DEC( 1234.865),    S(6),   B_PTR,       0,      12 },
        {  L_,   DEC(-1234.865),    S(6),   B_PTR,      -1,      13 },
        {  L_,   DEC( 1234.865),    S(6),       0,      -1,      12 },

        {  L_,   SUBN_P,            F(0),   B_PTR,       0,       1 },
        {  L_,   SUBN_N,            F(0),   B_PTR,       0,       2 },
        {  L_,   INF_P,             F(0),   B_PTR,       0,       3 },
        {  L_,   INF_N,             F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_Q_P,           F(0),   B_PTR,       0,       3 },
        {  L_,   NAN_Q_N,           F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_S_P,           F(0),   B_PTR,       0,       4 },
        {  L_,   NAN_S_N,           F(0),   B_PTR,       0,       5 },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(B_PTR, k_BUFFER_SIZE, 'x');

            const int     LINE        = DATA[ti].d_line;
            const Type    DECIMAL     = DATA[ti].d_decimal;
            const Config  CONFIG      = DATA[ti].d_config;
            char         *BUFFER      = DATA[ti].d_buffer;
            const int     BUFFER_SIZE = DATA[ti].d_bufferSize;
            const int     EXPECTED    = DATA[ti].d_expected;

            int len = Util::format(BUFFER,
                                   BUFFER_SIZE,
                                   DECIMAL,
                                   CONFIG);

            LOOP3_ASSERT(LINE, len, EXPECTED, len == EXPECTED);
            ASSERTV(L_, B_PTR == bsl::search_n(B_PTR,
                                               B_PTR + k_BUFFER_SIZE,
                                               k_BUFFER_SIZE,
                                               'x'));
        }
    }
    {
        if (verbose) cout << "Loop-based test" << endl;

        typedef Util::ValueType128 Type;

        const char* SIGNIFICANDS[] = {                           "1",
                                                                "22",
                                                               "333",
                                                              "4444",
                                                             "55555",
                                                            "666666",
                                                           "7777777",
                                                          "88888888",
                                                         "999999999",
                                                        "1111111111",
                                                       "22222222222",
                                                      "333333333333",
                                                     "4444444444444",
                                                    "55555555555555",
                                                   "666666666666666",
                                                  "7777777777777777",
                                                 "88888888888888888",
                                                "999999999999999999",
                                               "1111111111111111111",
                                              "22222222222222222222",
                                             "333333333333333333333",
                                            "4444444444444444444444",
                                           "55555555555555555555555",
                                          "666666666666666666666666",
                                         "7777777777777777777777777",
                                        "88888888888888888888888888",
                                       "999999999999999999999999999",
                                      "1111111111111111111111111111",
                                     "22222222222222222222222222222",
                                    "333333333333333333333333333333",
                                   "4444444444444444444444444444444",
                                  "55555555555555555555555555555555",
                                 "666666666666666666666666666666666",
                                "7777777777777777777777777777777777",
        };
        const int NUM_SIGNIFCANDS = static_cast<int>(
                                                   sizeof SIGNIFICANDS
                                                   / sizeof *SIGNIFICANDS);

        const Config CONFIGURATIONS[] = { F(6176),
                                          S(33),
                                          N(33),
        };

        const int NUM_CONFIGURATIONS = static_cast<int>(
                                                 sizeof CONFIGURATIONS
                                                 / sizeof *CONFIGURATIONS);

        const int BUFFER_SIZE = 10000;
        char      BUFFER[BUFFER_SIZE];

        for (int ci = 0; ci < NUM_CONFIGURATIONS; ++ci) {

            const Config& CONFIG       = CONFIGURATIONS[ci];
            const int     EXPONENT_MIN = -6176;
            const int     EXPONENT_MAX =  6111;

            for (int si = 0; si < NUM_SIGNIFCANDS; ++si) {
                const char *SIGNIFICAND = SIGNIFICANDS[si];

                Type value = Util::parse128(SIGNIFICAND);

                for (int ei = EXPONENT_MIN; ei <= EXPONENT_MAX; ++ei) {
                    const int EXPONENT = ei;

                    value = Util::scaleB(value, EXPONENT);

                    const Type EXPECTED = value;

                    int len = Util::format(BUFFER,
                                           BUFFER_SIZE,
                                           value,
                                           CONFIG);

                    const Type RESULT = Util::parse128(
                                        bsl::string(BUFFER, len, pa).c_str());
                    LOOP3_ASSERT(L_,
                                 SIGNIFICAND,
                                 EXPONENT,
                                 Util::equal(RESULT, EXPECTED));
                }
            }
        }
    }
    {
        if (verbose) cout << "Table-driven test" << endl;

        typedef Util::ValueType128 Type;

        const Type SUBN_P  = Util::denormMin128();
        const Type SUBN_N  = Util::negate(SUBN_P);
        const Type INF_P   = Util::infinity128();
        const Type INF_N   = Util::negate(INF_P);
        const Type NAN_Q_P = Util::quietNaN128();
        const Type NAN_Q_N = Util::negate(NAN_Q_P);
        const Type NAN_S_P = Util::signalingNaN128();
        const Type NAN_S_N = Util::negate(NAN_S_P);
        const Type MAX_P   = Util::max128();
        const Type MAX_N   = Util::negate(MAX_P);
        const Type MIN_P   = Util::min128();
        const Type MIN_N   = Util::negate(MIN_P);

        static const struct {
            const int          d_line;
            const Type         d_decimal;
            const Config       d_config;
            const char        *d_expected;
        } DATA [] = {
            //-----------------------------------------------------
            // Line | Decimal   | Configuration |  Expected
            //-----------------------------------------------------

            // ----------------------------------------------------
            // FIXED format
            // C-1,4
            {  L_,    SUBN_P,         F(6176),     SUBNORMAL_DECIMAL_128 },
            {  L_,    SUBN_N,         F(6176), "-" SUBNORMAL_DECIMAL_128 },
            {  L_,    INF_P,          F(0),       "inf"                  },
            {  L_,    INF_N,          F(0),      "-inf"                  },
            {  L_,    NAN_Q_P,        F(0),       "nan"                  },
            {  L_,    NAN_Q_N,        F(0),      "-nan"                  },
            {  L_,    NAN_S_P,        F(0),       "snan"                 },
            {  L_,    NAN_S_N,        F(0),      "-snan"                 },
            {  L_,    MAX_P,          F(0),        MAX_DECIMAL_128       },
            {  L_,    MAX_N,          F(0),    "-" MAX_DECIMAL_128       },
            {  L_,    MIN_P,          F(6143),     MIN_DECIMAL_128       },
            {  L_,    MIN_N,          F(6143), "-" MIN_DECIMAL_128       },
            {  L_,    DEC(-0.0),      F(0),      "-0"                    },
            {  L_,    DEC(0.0),       F(0),       "0"                    },
            //------------------------------------------------------------
            // SCIENTIFIC format
            // C-1,5
            {  L_,    SUBN_P,            S(0),    "1e-6176"              },
            {  L_,    SUBN_N,            S(0),   "-1e-6176"              },
            {  L_,    INF_P,             S(0),    "inf"                  },
            {  L_,    INF_N,             S(0),   "-inf"                  },
            {  L_,    NAN_Q_P,           S(0),    "nan"                  },
            {  L_,    NAN_Q_N,           S(0),   "-nan"                  },
            {  L_,    NAN_S_P,           S(0),    "snan"                 },
            {  L_,    NAN_S_N,           S(0),   "-snan"                 },
            {  L_,    MAX_P,             S(33),
                             "9.999999999999999999999999999999999e+6144" },
            {  L_,    MAX_N,             S(33),
                            "-9.999999999999999999999999999999999e+6144" },
            {  L_,    MAX_P,             S(0),    "1e+6145"              },
            {  L_,    MAX_N,             S(0),   "-1e+6145"              },
            {  L_,    MAX_P,             S(1),    "1.0e+6145"            },
            {  L_,    MAX_N,             S(1),   "-1.0e+6145"            },
            {  L_,    MIN_P,             S(0),    "1e-6143"              },
            {  L_,    MIN_N,             S(0),   "-1e-6143"              },
            {  L_,    DEC(-0.0),         S(0),   "-0e+00"                },
            {  L_,    DEC(0.0),          S(0),    "0e+00"                },
            {  L_,    DEC(0.0),          S(1),    "0.0e+00"              },
            {  L_,    DEC(0.00),         S(2),    "0.00e+00"             },
            {  L_,    DEC(0.000),        S(3),    "0.000e+00"            },
            //-------------------------------------------------------------
            // NATURAL  format
            // C-6,14
            {  L_,    DEC(1E-7),         N(0),     "1e-07"           },
            {  L_,    DEC(1E-6),         N(0),     "0.000001"        },
            {  L_,    DEC(1.1E-6),       N(0),     "0.0000011"       },
            {  L_,    DEC(1.11E-6),      N(0),     "0.00000111"      },
            {  L_,    DEC(1.111E-6),     N(0),     "0.000001111"     },
            {  L_,    DEC(1.1111E-6),    N(0),     "0.0000011111"    },
            {  L_,    DEC(1.11111E-6),   N(0),     "0.00000111111"   },
            {  L_,    DEC(1.111111E-6),  N(0),     "0.000001111111"  },
            {  L_,    DEC(1.1111111E-6), N(0),     "0.0000011111111" },

            {  L_,    DEC(1E+0),         N(0),     "1"               },
            {  L_,    DEC(1.1E+1),       N(0),     "11"              },
            {  L_,    DEC(1.11E+2),      N(0),     "111"             },
            {  L_,    DEC(1.111E+3),     N(0),     "1111"            },
            {  L_,    DEC(1.1111E+4),    N(0),     "11111"           },
            {  L_,    DEC(1.11111E+5),   N(0),     "111111"          },
            {  L_,    DEC(1.111111E+6),  N(0),     "1111111"         },
            {  L_,    DEC(1.111111E+7),  N(0),     "1.111111e+07"    },

            {  L_,    DEC(1234567E+2),   N(0),     "1.234567e+08"    },
            {  L_,    DEC(1234567E+1),   N(1),     "1.234567e+07"    },
            {  L_,    DEC(1234567E-0),   N(2),     "1234567"         },
            {  L_,    DEC(1234567E-1),   N(3),     "123456.7"        },
            {  L_,    DEC(1234567E-2),   N(4),     "12345.67"        },
            {  L_,    DEC(1234567E-3),   N(5),     "1234.567"        },
            {  L_,    DEC(1234567E-4),   N(6),     "123.4567"        },
            {  L_,    DEC(1234567E-5),   N(7),     "12.34567"        },
            {  L_,    DEC(1234567E-6),   N(8),     "1.234567"        },
            {  L_,    DEC(1234567E-7),   N(9),     "0.1234567"       },
            {  L_,    DEC(1234567E-8),   N(8),     "0.01234567"      },
            {  L_,    DEC(1234567E-9),   N(7),     "0.001234567"     },
            {  L_,    DEC(1234567E-10),  N(6),     "0.0001234567"    },
            {  L_,    DEC(1234567E-11),  N(5),     "0.00001234567"   },
            {  L_,    DEC(1234567E-12),  N(4),     "0.000001234567"  },
            {  L_,    DEC(1234567E-13),  N(3),     "1.234567e-07"    },
            {  L_,    DEC(1234567E-14),  N(2),     "1.234567e-08"    },
            //-------------------------------------------------------------
            // C-7
            //-------------------------------------------------------------
            // Test 'sign' attribute
#define CONFIG(SIGN) Config(0,                  \
                            Config::e_FIXED,    \
                            Config::SIGN)

            {  L_,    DEC( 123.0),    CONFIG(e_NEGATIVE_ONLY),  "123" },
            {  L_,    DEC(-123.0),    CONFIG(e_NEGATIVE_ONLY), "-123" },
            {  L_,    DEC( 123.0),    CONFIG(e_ALWAYS),        "+123" },
            {  L_,    DEC(-123.0),    CONFIG(e_ALWAYS),        "-123" },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'infinity' attribute
#define CONFIG(INF) Config(0,                       \
                           Config::e_SCIENTIFIC,    \
                           Config::e_NEGATIVE_ONLY, \
                           INF)

            {  L_,    INF_P,          CONFIG(""),         ""          },
            {  L_,    INF_P,          CONFIG("inf"),      "inf"       },
            {  L_,    INF_N,          CONFIG("Inf"),     "-Inf"       },
            {  L_,    INF_N,          CONFIG("INF"),     "-INF"       },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'nan' attribute
#define CONFIG(NAN) Config(0,                                   \
                           Config::e_SCIENTIFIC,                \
                           Config::e_NEGATIVE_ONLY,             \
                           "",                                  \
                           NAN)

            {  L_,    NAN_Q_P,        CONFIG(""),         ""          },
            {  L_,    NAN_Q_P,        CONFIG("nan"),      "nan"       },
            {  L_,    NAN_Q_N,        CONFIG("NaN"),     "-NaN"       },
            {  L_,    NAN_Q_N,        CONFIG("NAN"),     "-NAN"       },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'snan' attribute
#define CONFIG(SNAN) Config(0,                                          \
                            Config::e_SCIENTIFIC,                       \
                            Config::e_NEGATIVE_ONLY,                    \
                            "",                                         \
                            "",                                         \
                            SNAN)

            {  L_,    NAN_S_P,        CONFIG(""),          ""       },
            {  L_,    NAN_S_P,        CONFIG("snan"),      "snan"   },
            {  L_,    NAN_S_N,        CONFIG("sNaN"),     "-sNaN"   },
            {  L_,    NAN_S_N,        CONFIG("sNAN"),     "-sNAN"   },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'point'
#define CONFIG(POINT) Config(2,                         \
                             Config::e_SCIENTIFIC,      \
                             Config::e_NEGATIVE_ONLY,   \
                             "",                        \
                             "",                        \
                             "",                        \
                             POINT)

            {  L_,    DEC( 123.0),    CONFIG('.'),     "1.23e+02"     },
            {  L_,    DEC(-123.0),    CONFIG(','),    "-1,23e+02"     },
            {  L_,    DEC( 123.0),    CONFIG('_'),     "1_23e+02"     },
#undef CONFIG
                //-------------------------------------------------------------
                // Test 'exponent'
#define CONFIG(EXP) Config(2,                           \
                           Config::e_SCIENTIFIC,        \
                           Config::e_ALWAYS,            \
                           "",                          \
                           "",                          \
                           "",                          \
                           '.',                         \
                           EXP)

            {  L_,    DEC(-123.0),    CONFIG('E'),     "-1.23E+02"   },
            {  L_,    DEC( 123.0),    CONFIG('e'),     "+1.23e+02"   },
            {  L_,    DEC(-123.0),    CONFIG('^'),     "-1.23^+02"   },
#undef CONFIG
            //-------------------------------------------------------------
            // C-11
            {  L_,    DEC(1.11),         F(2),      "1.11"       },
            {  L_,    DEC(1.11),         F(3),      "1.110"      },
            {  L_,    DEC(1.11),         F(4),      "1.1100"     },
            {  L_,    DEC(1.11),         S(2),      "1.11e+00"   },
            {  L_,    DEC(1.11),         S(3),      "1.110e+00"  },
            {  L_,    DEC(1.11),         S(4),      "1.1100e+00" },
            //-------------------------------------------------------------
            // C-12
            {  L_,    DEC(4.44),         F(2),      "4.44"       },
            {  L_,    DEC(4.44),         F(1),      "4.4"        },
            {  L_,    DEC(4.44),         F(0),      "4"          },
            {  L_,    DEC(5.55),         F(2),      "5.55"       },
            {  L_,    DEC(5.55),         F(1),      "5.6"        },
            {  L_,    DEC(5.55),         F(0),      "6"          },
            {  L_,    DEC(9.99),         F(2),      "9.99"       },
            {  L_,    DEC(9.99),         F(1),      "10.0"       },
            {  L_,    DEC(9.99),         F(0),      "10"         },

            {  L_,    DEC(4.44),         S(2),      "4.44e+00"   },
            {  L_,    DEC(4.44),         S(1),      "4.4e+00"    },
            {  L_,    DEC(4.44),         S(0),      "4e+00"      },
            {  L_,    DEC(5.55),         S(2),      "5.55e+00"   },
            {  L_,    DEC(5.55),         S(1),      "5.6e+00"    },
            {  L_,    DEC(5.55),         S(0),      "6e+00"      },
            {  L_,    DEC(9.99),         S(2),      "9.99e+00"   },
            {  L_,    DEC(9.99),         S(1),      "1.0e+01"    },
            {  L_,    DEC(9.99),         S(0),      "1e+01"      },
            //-------------------------------------------------------------
            // C-13
            {  L_,    INF_P,             F(2),      "inf"        },
            {  L_,    INF_N,             F(3),     "-inf"        },
            {  L_,    NAN_Q_P,           F(4),      "nan"        },
            {  L_,    NAN_Q_N,           F(5),     "-nan"        },
            {  L_,    NAN_S_P,           F(6),      "snan"       },
            {  L_,    NAN_S_N,           F(7),     "-snan"       },

            {  L_,    INF_P,             S(5),      "inf"        },
            {  L_,    INF_N,             S(4),     "-inf"        },
            {  L_,    NAN_Q_P,           S(3),      "nan"        },
            {  L_,    NAN_Q_N,           S(2),     "-nan"        },
            {  L_,    NAN_S_P,           S(1),      "snan"       },
            {  L_,    NAN_S_N,           S(0),     "-snan"       },

            {  L_,    INF_P,             N(0),      "inf"        },
            {  L_,    INF_N,             N(0),     "-inf"        },
            {  L_,    NAN_Q_P,           N(0),      "nan"        },
            {  L_,    NAN_Q_N,           N(0),     "-nan"        },
            {  L_,    NAN_S_P,           N(0),      "snan"       },
            {  L_,    NAN_S_N,           N(0),     "-snan"       },
        };
        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        const int k_BUFFER_SIZE = 10000;
        char      buffer[k_BUFFER_SIZE];

        for (int ti = 0; ti < NUM_DATA; ++ti) {

            bsl::fill_n(&buffer[0], k_BUFFER_SIZE, 'x');

            const int         LINE      = DATA[ti].d_line;
            const Type        DECIMAL32 = DATA[ti].d_decimal;
            const Config      CONFIG    = DATA[ti].d_config;
            const bsl::string EXPECTED(DATA[ti].d_expected, pa);

            int len = Util::format(buffer,
                                   k_BUFFER_SIZE,
                                   DECIMAL32,
                                   CONFIG);

            const bsl::string RESULT(buffer, len, pa);
            if (veryVerbose) { P_(len) P(RESULT); }

            LOOP3_ASSERT(LINE, RESULT, EXPECTED, RESULT == EXPECTED);
            LOOP3_ASSERT(LINE,
                         len,
                         EXPECTED.length(),
                         len == static_cast<int>(EXPECTED.length()));

            //-------------------------------------------------------------
            // C-9
            LOOP2_ASSERT(LINE, buffer[len], 'x' == buffer[len]);

            //-------------------------------------------------------------
            // C-10
            if (FP_NORMAL == Util::classify(DECIMAL32) &&
                Config::e_NATURAL != CONFIG.style())
            {
                const char *BEGIN     = &buffer[0];
                const char *END       = &buffer[len];
                const char *POINT_POS = bsl::find(BEGIN,
                                                  END,
                                                  CONFIG.decimalPoint());
                if (POINT_POS == END) {
                    LOOP2_ASSERT(LINE,
                                 CONFIG.precision(),
                                 0 == CONFIG.precision());
                }
                else {
                    const char *EXPONENT_POS = bsl::find(
                                                        POINT_POS,
                                                        END,
                                                        CONFIG.exponent());
                    LOOP3_ASSERT(LINE,
                                 CONFIG.precision(),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS),
                                 bsl::distance(POINT_POS + 1,
                                               EXPONENT_POS)
                                 == CONFIG.precision());
                }
            }
        }

        if (veryVerbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            if (veryVerbose) cout << "\t'buffer == NULL'" << endl;
            {
                const int    k_SIZE = 1000;
                char         BUFFER[k_SIZE];
                const Type   V = Util::makeDecimalRaw128(0, 0);
                const Config CFG(6);

                ASSERT_PASS(Util::format(BUFFER, k_SIZE, V, CFG));
                ASSERT_FAIL(Util::format(     0, k_SIZE, V, CFG));
            }
        }
    }
#undef DEC
}

void TestDriver::testCase17()
{
    // ------------------------------------------------------------------------
    // TESTING 'scaleB'
    //
    // Concerns:
    //: 1 That if the sum of the specified 'exponent' and value's exponent is
    //:   in the range of exponents supported by tested decimal type then the
    //:   sum is assigned to resultant value's exponent with the value's
    //:   significand remaining unchanged.
    //:
    //: 2 That if the sum of the specified 'exponent' and value's exponent
    //:   exceeds the max exponent value supported by tested decimal type then
    //:   the max exponent value is assigned to the resultant exponent and the
    //:   significand value is 'normalized' by multiplying to 10 raised to the
    //:   difference between the exponent and max exponent value.  If the
    //:   resultant number of decimal places exceeds the number supported by
    //:   the tested type then infinity is returned and 'errno' is set the
    //:   value of 'ERANGE' macro.
    //:
    //: 3 That if the sum of the specified 'exponent' and value's exponent
    //:   is less than the min exponent value supported by tested decimal type
    //:   then the min exponent value is assigned to the resultant exponent and
    //:   the significand value is 'normalized' by dividing by 10 raised to the
    //:   difference between the max and the exponent value.  The significand
    //:   value is rounded halfway cases away from zero.
    //:
    //: 4 That if the value is 0, infinity or quiet NaN then the value is
    //:   retured.
    //:
    //: 5 That if the value is signaling NaN, then quiet NaN is returned and
    //:   'errno' is set the value of 'EDOM' macro.
    //
    // Plan:
    //: 1 Using table-driven technique:
    //:
    //:   1 Specify a set of arguments representing distinct decimal type
    //:     values and expected result of 'scaleB()' method.  (C-1)
    //:
    //:   2 Specify a set of decimal values which significand values have
    //:     decimal places from 1 to max number of decimal places supported by
    //:     the tested type.  Specify a set of exponent values so that
    //:     resultant exponent values equal to the max exponent and ensure that
    //:     the significand values are normalized correctly.  (C-2)
    //:
    //:   3 Specify a set of decimal values which significands values have
    //:     decimal places from 1 to max number of decimal places supported by
    //:     the tested type.  Specify a set of exponent values so that
    //:     resultant exponent values equal to the min exponent and ensure that
    //:     the significand values are normalized correctly.  (C-2)
    //:
    //:   4 Specify a set of special decimal values and ensure 'scaleB' returns
    //:     correct values and writes appropriate error codes to 'errno'.
    //:     (C-4,5)
    //
    // Testing:
    //   scaleB(ValueType32,  int)
    //   scaleB(ValueType64,  int)
    //   scaleB(ValueType128, int)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING 'scaleB'" << endl
                      << "================" << endl;

    {
#define DEC(X) Util::parse32(#X)
        typedef Util::ValueType32 Obj;

        const Obj MAX_P   =              Util::max32();
        const Obj NAN_P   =              Util::quietNaN32();
        const Obj NAN_N   = Util::negate(Util::quietNaN32());
        const Obj INF_P   =              Util::infinity32();
        const Obj INF_N   = Util::negate(Util::infinity32());
        const Obj SNAN_P  =              Util::signalingNaN32();

        struct {
            int d_line;
            Obj d_x;
            int d_exponent;
            Obj d_expected;
            int d_errno;
        } DATA[] = {
        //----------------------------------------------------------------
        // LINE |     X         | EXPONENT   | EXPECTED        | ERRNO
        //----------------------------------------------------------------
            { L_, DEC(0),          0,          DEC( 0),               0 },
            { L_, DEC(1),          0,          DEC( 1),               0 },
            { L_, DEC(1),          1,          DEC(10),               0 },
            { L_, DEC(1),         -1,          DEC(0.1),              0 },
            { L_, INF_P,           1,          INF_P,                 0 },
            { L_, INF_N,           1,          INF_N,                 0 },
            { L_, NAN_P,           1,          NAN_P,                 0 },
            { L_, NAN_N,           1,          NAN_N,                 0 },
            { L_, SNAN_P,          1,          NAN_P,              EDOM },
            { L_, DEC(1e-101),     101 + 96,   DEC(1e+96),            0 },
            { L_, DEC(1e+96),     -96 - 101,   DEC(1e-101),           0 },
            { L_, DEC(1),          INT_MAX,    INF_P,            ERANGE },
            { L_, DEC(1),         -INT_MAX,    DEC(0),                0 },

            { L_, DEC(9999999.0),   89,        DEC(9999999e+89),      0 },
            { L_, DEC(9999999.0),   90,        DEC(9999999e+90),      0 },
            { L_, DEC(999999.0),    91,        DEC(9999990e+90),      0 },
            { L_, DEC(99999.0),     92,        DEC(9999900e+90),      0 },
            { L_, DEC(9999.0),      93,        DEC(9999000e+90),      0 },
            { L_, DEC(999.0),       94,        DEC(9990000e+90),      0 },
            { L_, DEC(99.0),        95,        DEC(9900000e+90),      0 },
            { L_, DEC(9.0),         96,        DEC(9000000e+90),      0 },
            { L_, DEC(9.0),         97,        INF_P,            ERANGE },

            { L_, MAX_P,          -192,        DEC(1000000e-101),     0 },
            { L_, MAX_P,          -193,        DEC( 100000e-101),     0 },
            { L_, MAX_P,          -194,        DEC(  10000e-101),     0 },
            { L_, MAX_P,          -195,        DEC(   1000e-101),     0 },
            { L_, MAX_P,          -196,        DEC(    100e-101),     0 },
            { L_, MAX_P,          -197,        DEC(     10e-101),     0 },
            { L_, MAX_P,          -198,        DEC(      1e-101),     0 },
            { L_, MAX_P,          -199,        DEC(      0     ),     0 },
        };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE     = DATA[ti].d_line;
            const Obj& X        = DATA[ti].d_x;
            const int  EXPONENT = DATA[ti].d_exponent;
            const Obj& EXPECTED = DATA[ti].d_expected;
            const int  ERRNO    = DATA[ti].d_errno;

            errno = 0;
            const Obj RESULT = Util::scaleB(X, EXPONENT);

            LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
        }
#undef DEC
    }

    {
#define DEC(X) Util::parse64(#X)
        typedef Util::ValueType64 Obj;

        const Obj MAX_P   =              Util::max64();
        const Obj NAN_P   =              Util::quietNaN64();
        const Obj NAN_N   = Util::negate(Util::quietNaN64());
        const Obj INF_P   =              Util::infinity64();
        const Obj INF_N   = Util::negate(Util::infinity64());
        const Obj SNAN_P  =              Util::signalingNaN64();

        struct {
            int d_line;
            Obj d_x;
            int d_exponent;
            Obj d_expected;
            int d_errno;
        } DATA[] = {
        //-------------------------------------------------------------
        // LINE |     X       |  EXPONENT   | EXPECTED        | ERRNO
        //-------------------------------------------------------------
            { L_, DEC(0),        0,           DEC( 0),              0 },
            { L_, DEC(1),        0,           DEC( 1),              0 },
            { L_, DEC(1),        1,           DEC(10),              0 },
            { L_, DEC(1),       -1,           DEC(0.1),             0 },
            { L_, INF_P,         1,           INF_P,                0 },
            { L_, INF_N,         1,           INF_N,                0 },
            { L_, NAN_P,         1,           NAN_P,                0 },
            { L_, NAN_N,         1,           NAN_N,                0 },
            { L_, SNAN_P,        1,           NAN_P,             EDOM },
            { L_, DEC(1e-398),   398 + 369,   DEC(1e+369),          0 },
            { L_, DEC(1e+369),  -369 - 398,   DEC(1e-398),          0 },
            { L_, DEC(1),        INT_MAX,     INF_P,           ERANGE },
            { L_, DEC(1),       -INT_MAX,     DEC(0),              0 },

        //--------------------------------------------------------------------
        // LINE |    X                  | EXP |    EXPECTED      |     | ERRNO
        //--------------------------------------------------------------------
           { L_, DEC(9999999999999999.0), 369, DEC(9999999999999999e+369), 0 },
           { L_, DEC(999999999999999.0),  370, DEC(9999999999999990e+369), 0 },
           { L_, DEC(99999999999999.0),   371, DEC(9999999999999900e+369), 0 },
           { L_, DEC(9999999999999.0),    372, DEC(9999999999999000e+369), 0 },
           { L_, DEC(999999999999.0),     373, DEC(9999999999990000e+369), 0 },
           { L_, DEC(99999999999.0),      374, DEC(9999999999900000e+369), 0 },
           { L_, DEC(9999999999.0),       375, DEC(9999999999000000e+369), 0 },
           { L_, DEC(999999999.0),        376, DEC(9999999990000000e+369), 0 },
           { L_, DEC(99999999.0),         377, DEC(9999999900000000e+369), 0 },
           { L_, DEC(9999999.0),          378, DEC(9999999000000000e+369), 0 },
           { L_, DEC(999999.0),           379, DEC(9999990000000000e+369), 0 },
           { L_, DEC(99999.0),            380, DEC(9999900000000000e+369), 0 },
           { L_, DEC(9999.0),             381, DEC(9999000000000000e+369), 0 },
           { L_, DEC(999.0),              382, DEC(9990000000000000e+369), 0 },
           { L_, DEC(99.0),               383, DEC(9900000000000000e+369), 0 },
           { L_, DEC(9.0),                384, DEC(9000000000000000e+369), 0 },
           { L_, DEC(9.0),                385, INF_P,                 ERANGE },

           { L_, MAX_P,                  -767, DEC(9999999999999999e-398), 0 },
           { L_, MAX_P,                  -768, DEC(1000000000000000e-398), 0 },
           { L_, MAX_P,                  -769, DEC( 100000000000000e-398), 0 },
           { L_, MAX_P,                  -770, DEC(  10000000000000e-398), 0 },
           { L_, MAX_P,                  -771, DEC(   1000000000000e-398), 0 },
           { L_, MAX_P,                  -772, DEC(    100000000000e-398), 0 },
           { L_, MAX_P,                  -773, DEC(     10000000000e-398), 0 },
           { L_, MAX_P,                  -774, DEC(      1000000000e-398), 0 },
           { L_, MAX_P,                  -775, DEC(       100000000e-398), 0 },
           { L_, MAX_P,                  -776, DEC(        10000000e-398), 0 },
           { L_, MAX_P,                  -777, DEC(         1000000e-398), 0 },
           { L_, MAX_P,                  -778, DEC(          100000e-398), 0 },
           { L_, MAX_P,                  -779, DEC(           10000e-398), 0 },
           { L_, MAX_P,                  -780, DEC(            1000e-398), 0 },
           { L_, MAX_P,                  -781, DEC(             100e-398), 0 },
           { L_, MAX_P,                  -782, DEC(              10e-398), 0 },
           { L_, MAX_P,                  -783, DEC(               1e-398), 0 },
           { L_, MAX_P,                  -784, DEC(               0     ), 0 },
            };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE     = DATA[ti].d_line;
            const Obj& X        = DATA[ti].d_x;
            const int  EXPONENT = DATA[ti].d_exponent;
            const Obj& EXPECTED = DATA[ti].d_expected;
            const int  ERRNO    = DATA[ti].d_errno;

            errno = 0;
            const Obj RESULT = Util::scaleB(X, EXPONENT);

            LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
        }
#undef DEC
    }

    {
#define DEC(X) Util::parse128(#X)
        typedef Util::ValueType128 Obj;

        const Obj MAX_P   =              Util::max128();
        const Obj NAN_P   =              Util::quietNaN128();
        const Obj NAN_N   = Util::negate(Util::quietNaN128());
        const Obj INF_P   =              Util::infinity128();
        const Obj INF_N   = Util::negate(Util::infinity128());
        const Obj SNAN_P  =              Util::signalingNaN128();

        struct {
            int d_line;
            Obj d_x;
            int d_exponent;
            Obj d_expected;
            int d_errno;
        } DATA[] = {
        //-------------------------------------------------------------
        // LINE |     X       |  EXPONENT   | EXPECTED        | ERRNO
        //-------------------------------------------------------------
            { L_, DEC(0),        0,           DEC( 0),              0 },
            { L_, DEC(1),        0,           DEC( 1),              0 },
            { L_, DEC(1),        1,           DEC(10),              0 },
            { L_, DEC(1),       -1,           DEC(0.1),             0 },
            { L_, INF_P,         1,           INF_P,                0 },
            { L_, INF_N,         1,           INF_N,                0 },
            { L_, NAN_P,         1,           NAN_P,                0 },
            { L_, NAN_N,         1,           NAN_N,                0 },
            { L_, SNAN_P,        1,           NAN_P,             EDOM },
            { L_, DEC(1e-6176),  6176 + 6144, DEC(1e+6144),         0 },
            { L_, DEC(1e+6144), -6144 - 6176, DEC(1e-6176),         0 },
            { L_, DEC(1),        INT_MAX,     INF_P,           ERANGE },
            { L_, DEC(1),       -INT_MAX,     DEC( 0),              0 },

        //--------------------------------------------------------------
        // LINE |                 X                        | EXP |
        //      |                 EXPECTED                 |     | ERRNO
        //--------------------------------------------------------------
            { L_, DEC(9999999999999999999999999999999999.0), 6110,
                  DEC(9999999999999999999999999999999999e+6110),    0 },
            { L_, DEC(9999999999999999999999999999999999.0), 6111,
                  DEC(9999999999999999999999999999999999e+6111),    0 },
            { L_, DEC(999999999999999999999999999999999.0),  6112,
                  DEC(9999999999999999999999999999999990e+6111),    0 },
            { L_, DEC(99999999999999999999999999999999.0),   6113,
                  DEC(9999999999999999999999999999999900e+6111),    0 },
            { L_, DEC(9999999999999999999999999999999.0),    6114,
                  DEC(9999999999999999999999999999999000e+6111),    0 },
            { L_, DEC(999999999999999999999999999999.0),     6115,
                  DEC(9999999999999999999999999999990000e+6111),    0 },
            { L_, DEC(99999999999999999999999999999.0),      6116,
                  DEC(9999999999999999999999999999900000e+6111),    0 },
            { L_, DEC(9999999999999999999999999999.0),       6117,
                  DEC(9999999999999999999999999999000000e+6111),    0 },
            { L_, DEC(999999999999999999999999999.0),        6118,
                  DEC(9999999999999999999999999990000000e+6111),    0 },
            { L_, DEC(99999999999999999999999999.0),         6119,
                  DEC(9999999999999999999999999900000000e+6111),    0 },
            { L_, DEC(9999999999999999999999999.0),          6120,
                  DEC(9999999999999999999999999000000000e+6111),    0 },
            { L_, DEC(999999999999999999999999.0),           6121,
                  DEC(9999999999999999999999990000000000e+6111),    0 },
            { L_, DEC(99999999999999999999999.0),            6122,
                  DEC(9999999999999999999999900000000000e+6111),    0 },
            { L_, DEC(9999999999999999999999.0),             6123,
                  DEC(9999999999999999999999000000000000e+6111),    0 },
            { L_, DEC(999999999999999999999.0),              6124,
                  DEC(9999999999999999999990000000000000e+6111),    0 },
            { L_, DEC(99999999999999999999.0),               6125,
                  DEC(9999999999999999999900000000000000e+6111),    0 },
            { L_, DEC(9999999999999999999.0),                6126,
                  DEC(9999999999999999999000000000000000e+6111),    0 },
            { L_, DEC(999999999999999999.0),                 6127,
                  DEC(9999999999999999990000000000000000e+6111),    0 },
            { L_, DEC(99999999999999999.0),                  6128,
                  DEC(9999999999999999900000000000000000e+6111),    0 },
            { L_, DEC(9999999999999999.0),                   6129,
                  DEC(9999999999999999000000000000000000e+6111),    0 },
            { L_, DEC(999999999999999.0),                    6130,
                  DEC(9999999999999990000000000000000000e+6111),    0 },
            { L_, DEC(99999999999999.0),                     6131,
                  DEC(9999999999999900000000000000000000e+6111),    0 },
            { L_, DEC(9999999999999.0),                      6132,
                  DEC(9999999999999000000000000000000000e+6111),    0 },
            { L_, DEC(999999999999.0),                       6133,
                  DEC(9999999999990000000000000000000000e+6111),    0 },
            { L_, DEC(99999999999.0),                        6134,
                  DEC(9999999999900000000000000000000000e+6111),    0 },
            { L_, DEC(9999999999.0),                         6135,
                  DEC(9999999999000000000000000000000000e+6111),    0 },
            { L_, DEC(999999999.0),                          6136,
                  DEC(9999999990000000000000000000000000e+6111),    0 },
            { L_, DEC(99999999.0),                           6137,
                  DEC(9999999900000000000000000000000000e+6111),    0 },
            { L_, DEC(9999999.0),                            6138,
                  DEC(9999999000000000000000000000000000e+6111),    0 },
            { L_, DEC(999999.0),                             6139,
                  DEC(9999990000000000000000000000000000e+6111),    0 },
            { L_, DEC(99999.0),                              6140,
                  DEC(9999900000000000000000000000000000e+6111),    0 },
            { L_, DEC(9999.0),                               6141,
                  DEC(9999000000000000000000000000000000e+6111),    0 },
            { L_, DEC(999.0),                                6142,
                  DEC(9990000000000000000000000000000000e+6111),    0 },
            { L_, DEC(99.0),                                 6143,
                  DEC(9900000000000000000000000000000000e+6111),    0 },
            { L_, DEC(9.0),                                  6144,
                  DEC(9000000000000000000000000000000000e+6111),    0 },
            { L_, DEC(9.0),                                  6145,
                  INF_P,                                       ERANGE },

  //---------------------------------------------------------------------------
  // LINE |  X   |  EXP  |     EXPECTED                                 | ERRNO
  //---------------------------------------------------------------------------
      { L_, MAX_P, -12287, DEC(9999999999999999999999999999999999e-6176),  0 },
      { L_, MAX_P, -12288, DEC(1000000000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12289, DEC( 100000000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12290, DEC(  10000000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12291, DEC(   1000000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12292, DEC(    100000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12293, DEC(     10000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12294, DEC(      1000000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12295, DEC(       100000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12296, DEC(        10000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12297, DEC(         1000000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12298, DEC(          100000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12299, DEC(           10000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12300, DEC(            1000000000000000000000e-6176),  0 },
      { L_, MAX_P, -12301, DEC(             100000000000000000000e-6176),  0 },
      { L_, MAX_P, -12302, DEC(              10000000000000000000e-6176),  0 },
      { L_, MAX_P, -12303, DEC(               1000000000000000000e-6176),  0 },
      { L_, MAX_P, -12304, DEC(                100000000000000000e-6176),  0 },
      { L_, MAX_P, -12305, DEC(                 10000000000000000e-6176),  0 },
      { L_, MAX_P, -12306, DEC(                  1000000000000000e-6176),  0 },
      { L_, MAX_P, -12307, DEC(                   100000000000000e-6176),  0 },
      { L_, MAX_P, -12308, DEC(                    10000000000000e-6176),  0 },
      { L_, MAX_P, -12309, DEC(                     1000000000000e-6176),  0 },
      { L_, MAX_P, -12310, DEC(                      100000000000e-6176),  0 },
      { L_, MAX_P, -12311, DEC(                       10000000000e-6176),  0 },
      { L_, MAX_P, -12312, DEC(                        1000000000e-6176),  0 },
      { L_, MAX_P, -12313, DEC(                         100000000e-6176),  0 },
      { L_, MAX_P, -12314, DEC(                          10000000e-6176),  0 },
      { L_, MAX_P, -12315, DEC(                           1000000e-6176),  0 },
      { L_, MAX_P, -12316, DEC(                            100000e-6176),  0 },
      { L_, MAX_P, -12317, DEC(                             10000e-6176),  0 },
      { L_, MAX_P, -12318, DEC(                              1000e-6176),  0 },
      { L_, MAX_P, -12319, DEC(                               100e-6176),  0 },
      { L_, MAX_P, -12320, DEC(                                10e-6176),  0 },
      { L_, MAX_P, -12321, DEC(                                 1e-6176),  0 },
      { L_, MAX_P, -12322, DEC(                                 0      ),  0 },
      };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int  LINE     = DATA[ti].d_line;
            const Obj& X        = DATA[ti].d_x;
            const int  EXPONENT = DATA[ti].d_exponent;
            const Obj& EXPECTED = DATA[ti].d_expected;
            const int  ERRNO    = DATA[ti].d_errno;

            errno = 0;
            const Obj RESULT = Util::scaleB(X, EXPONENT);

            LOOP_ASSERT(LINE, nanEqual(RESULT, EXPECTED));
            LOOP3_ASSERT(LINE, ERRNO, errno, ERRNO == errno);
        }
#undef DEC
    }
}

void TestDriver::testCase16()
{
    // ------------------------------------------------------------------------
    // TESTING COMPARISON FUNCTIONS
    //
    // Concerns:
    //:  1 Infinities are at the ends of all ordered comparision arrangements.
    //:
    //:  2 Positive numbers are greater than negative numbers.
    //:
    //:  3 'NaN' is neither greater nor less than any value, including itself.
    //:
    //:  4 Zero compares neither less nor greater than itself.
    //:
    //:  5 Transitivity is preserved.
    //
    // Plan:
    //:  1 A set of representative values for 32, 64, and 128-bit types will be
    //:    created and each compared against each other, under assertion for
    //:    the correct result. (C-2,5)
    //:
    //:  2 Zeros of both signs will be in the data set. (C-4)
    //:
    //:  3 Infinities will be among the values (C-1)
    //:
    //:  4 A 'NaN' will be among the data. (C-3)
    //
    // Testing:
    //   less(ValueType32,  ValueType32)
    //   less(ValueType64,  ValueType64)
    //   less(ValueType128, ValueType128)
    //   greater(ValueType32,  ValueType32)
    //   greater(ValueType64,  ValueType64)
    //   greater(ValueType128, ValueType128)
    //   lessEqual(ValueType32,  ValueType32)
    //   lessEqual(ValueType64,  ValueType64)
    //   lessEqual(ValueType128, ValueType128)
    //   greaterEqual(ValueType32,  ValueType32)
    //   greaterEqual(ValueType64,  ValueType64)
    //   greaterEqual(ValueType128, ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING COMPARISON FUNCTIONS" << endl
                      << "============================" << endl;

    Util::ValueType32 snan32  = Util::parse32("sNaN");
    Util::ValueType32  nan32  = Util::parse32( "NaN");
    Util::ValueType64  nan64  = Util::parse64( "NaN");
    Util::ValueType128 nan128 = Util::parse128("NaN");

    // Check that all 'NaN' operations return false:

    ASSERT(!Util::less(nan32, nan32));
    ASSERT(!Util::greater(nan32, nan32));
    ASSERT(!Util::lessEqual(nan32, nan32));
    ASSERT(!Util::greaterEqual(nan32, nan32));

    ASSERT(!Util::less(nan64, nan64));
    ASSERT(!Util::greater(nan64, nan64));
    ASSERT(!Util::lessEqual(nan64, nan64));
    ASSERT(!Util::greaterEqual(nan64, nan64));

    ASSERT(!Util::less(nan128, nan128));
    ASSERT(!Util::greater(nan128, nan128));
    ASSERT(!Util::lessEqual(nan128, nan128));
    ASSERT(!Util::greaterEqual(nan128, nan128));

    struct {
        const char *number;
        const int order;
    } tests[] = {
        { "-Inf",   -100000 },
        { "-42e10", -   100 },
        { "-42",    -    90 },
        { "-1",     -    10 },
        { "-.1415", -     2 },
        { "-.0025", -     1 },
        { "-0",           0 },
        { "+0",           0 },
        { "+.0025", +     1 },
        { "+.1415", +     2 },
        { "+1",     +    10 },
        { "+42",    +    90 },
        { "+42e10", +   100 },
        { "+Inf",   +100000 }
    };
    const int numTests = static_cast<int>(sizeof(tests) / sizeof(tests[0]));

    for (int i = 0; i < numTests; ++i) {
        const char *const lhsValue = tests[i].number;
        const int         lhsOrder = tests[i].order;

        if (veryVerbose) cout << endl
                              << "lhsValue = " << lhsValue << endl;

        Util::ValueType32  lhs32  = Util::parse32( lhsValue);
        Util::ValueType64  lhs64  = Util::parse64( lhsValue);
        Util::ValueType128 lhs128 = Util::parse128(lhsValue);

        // Test 'NaN' against these values...

        errno = 0;
        ASSERT(        !Util::less(snan32, snan32)); ASSERT(EDOM == errno);
        errno = 0;
        ASSERT(     !Util::greater(snan32, snan32)); ASSERT(EDOM == errno);
        errno = 0;
        ASSERT(   !Util::lessEqual(snan32, snan32)); ASSERT(EDOM == errno);
        errno = 0;
        ASSERT(!Util::greaterEqual(snan32, snan32)); ASSERT(EDOM == errno);

        ASSERT(!Util::less( nan32, lhs32));
        ASSERT(!Util::less(lhs32,  nan32));
        ASSERT(!Util::greater( nan32, lhs32));
        ASSERT(!Util::greater(lhs32,  nan32));
        ASSERT(!Util::lessEqual( nan32, lhs32));
        ASSERT(!Util::lessEqual(lhs32,  nan32));
        ASSERT(!Util::greaterEqual( nan32, lhs32));
        ASSERT(!Util::greaterEqual(lhs32,  nan32));
        ASSERT(!Util::less(nan64, lhs64));
        ASSERT(!Util::less(lhs64, nan64));
        ASSERT(!Util::greater(nan64, lhs64));
        ASSERT(!Util::greater(lhs64, nan64));
        ASSERT(!Util::lessEqual(nan64, lhs64));
        ASSERT(!Util::lessEqual(lhs64, nan64));
        ASSERT(!Util::greaterEqual(nan64, lhs64));
        ASSERT(!Util::greaterEqual(lhs64, nan64));

        ASSERT(!Util::less(nan128, lhs128));
        ASSERT(!Util::less(lhs128, nan128));
        ASSERT(!Util::greater(nan128, lhs128));
        ASSERT(!Util::greater(lhs128, nan128));
        ASSERT(!Util::lessEqual(nan128, lhs128));
        ASSERT(!Util::lessEqual(lhs128, nan128));
        ASSERT(!Util::greaterEqual(nan128, lhs128));
        ASSERT(!Util::greaterEqual(lhs128, nan128));

        for (int j = 0; j < numTests; ++j) {
            const char *const rhsValue = tests[j].number;
            const int         rhsOrder = tests[j].order;
            if (veryVerbose) cout << endl
                                  << "rhsValue = " << rhsValue << endl;

            Util::ValueType32  rhs32  = Util::parse32( rhsValue);
            Util::ValueType64  rhs64  = Util::parse64( rhsValue);
            Util::ValueType128 rhs128 = Util::parse128(rhsValue);

            // Test Decimal32.
            {
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::less(lhs32, rhs32)         == (lhsOrder< rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greater(lhs32, rhs32)      == (lhsOrder> rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::lessEqual(lhs32, rhs32)    == (lhsOrder<=rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greaterEqual(lhs32, rhs32) == (lhsOrder>=rhsOrder));
            }

            // Test Decimal64.
            {
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::less(lhs64, rhs64)         == (lhsOrder< rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greater(lhs64, rhs64)      == (lhsOrder> rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::lessEqual(lhs64, rhs64)    == (lhsOrder<=rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greaterEqual(lhs64, rhs64) == (lhsOrder>=rhsOrder));
            }

            // Test Decimal128.
            {
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::less(lhs128, rhs128)        ==(lhsOrder< rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greater(lhs128, rhs128)     ==(lhsOrder> rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::lessEqual(lhs128, rhs128)   ==(lhsOrder<=rhsOrder));
                ASSERTV(
                 lhsValue, rhsValue,
                 lhsOrder, rhsOrder,
                 Util::greaterEqual(lhs128, rhs128)==(lhsOrder>=rhsOrder));
            }
        }
    }
}

void TestDriver::testCase15()
{
    // ------------------------------------------------------------------------
    // TESTING 'binaryToDecimalXX'
    //
    // Concerns:
    //:  1 Conversion to Decimal preserves precise value, where possible.  The
    //:    bases of 10, and 2 are only able to cross convert when the actual
    //:    value is proper sum of fractions of powers-of-two.
    //
    // Plan:
    //:  1 Convert several values that are 'integral' and sums of power-of-two
    //:    fractions (which just counts as whole numbers).  (C-1)
    //
    // Testing:
    //   binaryToDecimal32 (float)
    //   binaryToDecimal32 (double)
    //   binaryToDecimal64 (float)
    //   binaryToDecimal64 (double)
    //   binaryToDecimal128(float)
    //   binaryToDecimal128(double)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING 'binaryToDecimalXX'" << endl
                      << "===========================" << endl;

    // 'binaryToDecimal32(float)'

    {
        Util::ValueType32 value32;
        Util::ValueType32  test32;

        value32 = Util::parse32(         "0.0");
         test32 = Util::binaryToDecimal32(0.0f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "1.0");
         test32 = Util::binaryToDecimal32(1.0f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "10.");
         test32 = Util::binaryToDecimal32(10.f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "42.");
         test32 = Util::binaryToDecimal32(42.f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-1.0");
         test32 = Util::binaryToDecimal32(-1.0f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-10.");
         test32 = Util::binaryToDecimal32(-10.f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-42.");
         test32 = Util::binaryToDecimal32(-42.f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "0.5");
         test32 = Util::binaryToDecimal32(0.5f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "0.25");
         test32 = Util::binaryToDecimal32(0.25f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-0.5");
         test32 = Util::binaryToDecimal32(-0.5f);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-0.25");
         test32 = Util::binaryToDecimal32(-0.25f);
        ASSERT(Util::equal(value32, test32));

        errno   = 0;
        value32 = Util::parse32(         "sNaN");
        test32  = Util::binaryToDecimal32(
                                  bsl::numeric_limits<float>::signaling_NaN());
        ASSERT(!Util::equal(value32, test32));
        ASSERT(!Util::equal(test32,  test32));
        ASSERT(EDOM == errno);
    }

    // binaryToDecimal32(double)

    {
        Util::ValueType32 value32;
        Util::ValueType32  test32;

        value32 = Util::parse32(         "nan");
        test32 = Util::binaryToDecimal32(
                                      bsl::numeric_limits<float>::quiet_NaN());
        ASSERT(!Util::equal(value32, test32));
        ASSERT(!Util::equal(test32,  test32));

        value32 = Util::parse32(        "-nan");
        test32 = Util::binaryToDecimal32(
                                     -bsl::numeric_limits<float>::quiet_NaN());
        ASSERT(!Util::equal(value32, test32));
        ASSERT(!Util::equal(test32,  test32));

        value32 = Util::parse32(         "0.0");
         test32 = Util::binaryToDecimal32(0.0);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "1.0");
         test32 = Util::binaryToDecimal32(1.0);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "10.");
         test32 = Util::binaryToDecimal32(10.);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "42.");
         test32 = Util::binaryToDecimal32(42.);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-1.0");
         test32 = Util::binaryToDecimal32(-1.0);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-10.");
         test32 = Util::binaryToDecimal32(-10.);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-42.");
         test32 = Util::binaryToDecimal32(-42.);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "0.5");
         test32 = Util::binaryToDecimal32(0.5);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "0.25");
         test32 = Util::binaryToDecimal32(0.25);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-0.5");
         test32 = Util::binaryToDecimal32(-0.5);
        ASSERT(Util::equal(value32, test32));

        value32 = Util::parse32(         "-0.25");
         test32 = Util::binaryToDecimal32(-0.25);
        ASSERT(Util::equal(value32, test32));

        errno = 0;
        value32 = Util::parse32(          "Inf");
         test32 = Util::binaryToDecimal32(1e+100);
        ASSERT(Util::equal(value32, test32));
        ASSERT(ERANGE == errno);

        errno = 0;
        value32 = Util::parse32(          "-Inf");
         test32 = Util::binaryToDecimal32(-1e+100);
        ASSERT(Util::equal(value32, test32));
        ASSERT(ERANGE == errno);

        errno = 0;
        value32 = Util::parse32(          "0.0");
         test32 = Util::binaryToDecimal32(1e-200);
        ASSERT(Util::equal(value32, test32));
        ASSERT(ERANGE == errno);

        errno = 0;
        value32 = Util::parse32(          "-0.0");
         test32 = Util::binaryToDecimal32(-1e-200);
        ASSERT(Util::equal(value32, test32));
        ASSERT(ERANGE == errno);
    }


    // 'binaryToDecimal64(float)'

    {
        Util::ValueType64 value64;
        Util::ValueType64  test64;

        value64 = Util::parse64(         "0.0");
         test64 = Util::binaryToDecimal64(0.0f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "1.0");
         test64 = Util::binaryToDecimal64(1.0f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "10.");
         test64 = Util::binaryToDecimal64(10.f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "42.");
         test64 = Util::binaryToDecimal64(42.f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-1.0");
         test64 = Util::binaryToDecimal64(-1.0f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-10.");
         test64 = Util::binaryToDecimal64(-10.f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-42.");
         test64 = Util::binaryToDecimal64(-42.f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "0.5");
         test64 = Util::binaryToDecimal64(0.5f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "0.25");
         test64 = Util::binaryToDecimal64(0.25f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-0.5");
         test64 = Util::binaryToDecimal64(-0.5f);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-0.25");
         test64 = Util::binaryToDecimal64(-0.25f);
        ASSERT(Util::equal(value64, test64));
    }

    // binaryToDecimal64(double)

    {
        Util::ValueType64 value64;
        Util::ValueType64  test64;

        value64 = Util::parse64(         "0.0");
         test64 = Util::binaryToDecimal64(0.0);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "1.0");
         test64 = Util::binaryToDecimal64(1.0);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "10.");
         test64 = Util::binaryToDecimal64(10.);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "42.");
         test64 = Util::binaryToDecimal64(42.);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-1.0");
         test64 = Util::binaryToDecimal64(-1.0);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-10.");
         test64 = Util::binaryToDecimal64(-10.);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-42.");
         test64 = Util::binaryToDecimal64(-42.);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "0.5");
         test64 = Util::binaryToDecimal64(0.5);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "0.25");
         test64 = Util::binaryToDecimal64(0.25);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-0.5");
         test64 = Util::binaryToDecimal64(-0.5);
        ASSERT(Util::equal(value64, test64));

        value64 = Util::parse64(         "-0.25");
         test64 = Util::binaryToDecimal64(-0.25);
        ASSERT(Util::equal(value64, test64));
    }

    // 'binaryToDecimal128(float)'

    {
        Util::ValueType128 value128;
        Util::ValueType128  test128;

        value128 = Util::parse128(         "0.0");
         test128 = Util::binaryToDecimal128(0.0f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "1.0");
         test128 = Util::binaryToDecimal128(1.0f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "10.");
         test128 = Util::binaryToDecimal128(10.f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "42.");
         test128 = Util::binaryToDecimal128(42.f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-1.0");
         test128 = Util::binaryToDecimal128(-1.0f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-10.");
         test128 = Util::binaryToDecimal128(-10.f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-42.");
         test128 = Util::binaryToDecimal128(-42.f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "0.5");
         test128 = Util::binaryToDecimal128(0.5f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "0.25");
         test128 = Util::binaryToDecimal128(0.25f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-0.5");
         test128 = Util::binaryToDecimal128(-0.5f);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-0.25");
         test128 = Util::binaryToDecimal128(-0.25f);
        ASSERT(Util::equal(value128, test128));
    }

    // binaryToDecimal128(double)

    {
        Util::ValueType128 value128;
        Util::ValueType128  test128;

        value128 = Util::parse128(         "0.0");
         test128 = Util::binaryToDecimal128(0.0);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "1.0");
         test128 = Util::binaryToDecimal128(1.0);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "10.");
         test128 = Util::binaryToDecimal128(10.);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "42.");
         test128 = Util::binaryToDecimal128(42.);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-1.0");
         test128 = Util::binaryToDecimal128(-1.0);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-10.");
         test128 = Util::binaryToDecimal128(-10.);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-42.");
         test128 = Util::binaryToDecimal128(-42.);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "0.5");
         test128 = Util::binaryToDecimal128(0.5);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "0.25");
         test128 = Util::binaryToDecimal128(0.25);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-0.5");
         test128 = Util::binaryToDecimal128(-0.5);
        ASSERT(Util::equal(value128, test128));

        value128 = Util::parse128(         "-0.25");
         test128 = Util::binaryToDecimal128(-0.25);
        ASSERT(Util::equal(value128, test128));
    }
}

void TestDriver::testCase14()
{
    // ------------------------------------------------------------------------
    // TESTING '[u]intXXToDecimalXX'
    //
    // Concerns:
    //:  1 '[u]intXXToDecimalXX' must convert the value as expected.
    //:
    //:  2 Conversion may not be by forwarding.
    //:
    //:  3 There are 4 overloads for each size, which need testing.
    //:
    //:  4 Rounding is handled appropriately.
    //
    //Plan:
    //:  1 Run numerous mantissas through the conversion functions and compare
    //:    the results with 'parse(mantissaAsString)'.  (C-1..4)
    //
    // Testing:
    //    int32ToDecimal32 (                   int)
    //   uint32ToDecimal32 (unsigned           int)
    //    int64ToDecimal32 (         long long int)
    //   uint64ToDecimal32 (unsigned long long int)
    //    int32ToDecimal64 (                   int)
    //   uint32ToDecimal64 (unsigned           int)
    //    int64ToDecimal64 (         long long int)
    //   uint64ToDecimal64 (unsigned long long int)
    //    int32ToDecimal128(                   int)
    //   uint32ToDecimal128(unsigned           int)
    //    int64ToDecimal128(         long long int)
    //   uint64ToDecimal128(unsigned long long int)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING '[u]intXXToDecimalXX'" << endl
                      << "=============================" << endl;

    for (int mi = 0; mi < NUM_TEST_NONZERO_MANTISSAS; ++mi) {
        const long long MANTISSA = TEST_NONZERO_MANTISSAS[mi];

        if (veryVerbose) cout << endl
                              << "Testing mantissa index: " << mi
                              << ", MANTISSA: " << MANTISSA << endl;

        char TEST_STRING[100];
        sprintf(TEST_STRING, "%lld", MANTISSA);

        Util::ValueType32  value32 = Util::parse32(TEST_STRING);
        Util::ValueType64  value64 = Util::parse64(TEST_STRING);
        Util::ValueType128 value128 = Util::parse128(TEST_STRING);

        if (MANTISSA >= 0) {
          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value32,
                                   Util::uint64ToDecimal32(
                              static_cast<unsigned long long>(MANTISSA))));

          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value64,
                                   Util::uint64ToDecimal64(
                              static_cast<unsigned long long>(MANTISSA))));


          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value128,
                                   Util::uint64ToDecimal128(
                              static_cast<unsigned long long>(MANTISSA))));
        }

        if ((MANTISSA >= bsl::numeric_limits<int>::min()) &&
            (MANTISSA <= bsl::numeric_limits<int>::max())) {
          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value32,
                                   Util::int32ToDecimal32(
                                   static_cast<int>(MANTISSA))));

          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value64,
                                   Util::int32ToDecimal64(
                                   static_cast<int>(MANTISSA))));


          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value128,
                                   Util::int32ToDecimal128(
                                   static_cast<int>(MANTISSA))));
        }
        if ((MANTISSA >= 0 ) &&
            (MANTISSA <= bsl::numeric_limits<unsigned int>::max())) {
          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value32,
                                   Util::uint32ToDecimal32(
                                   static_cast<unsigned int>(MANTISSA))));

          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value64,
                                   Util::uint32ToDecimal64(
                                   static_cast<unsigned int>(MANTISSA))));


          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value128,
                                   Util::uint32ToDecimal128(
                                   static_cast<unsigned int>(MANTISSA))));
        }

        // For 'long long'

        {
          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value32,
                                   Util::int64ToDecimal32(MANTISSA)));

          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value64,
                                   Util::int64ToDecimal64(MANTISSA)));


          LOOP2_ASSERT(MANTISSA, TEST_STRING, Util::equal(value128,
                                   Util::int64ToDecimal128(MANTISSA)));
        }
    }
}

void TestDriver::testCase13()
{
    // ------------------------------------------------------------------------
    // TESTING 'makeDecimal64'
    //
    // Concerns:
    //: 1 'makeDecimal64' passes its arguments to 'makeDecimal64Raw' and
    //:   'makeDecimal128Raw' correctly.
    //:
    //: 2 The correct rounding behavior is performed when the specified
    //:   mantissa has a magnitude too great to be represented by a 64-bit
    //:   decimal floating point value.
    //:
    //: 3 The correct rounding behavior is performed when the magnitude of the
    //:   specified number is too great to be represented by a 64-bit decimal
    //:   floating point value.
    //:
    //: 4 The correct sign is preserved when rounding to zero or infinite
    //:   values.
    //:
    //: 5 If the mantissa and exponent are in range for 64-bit decimal floating
    //:   point numbers (i.e., 'abs(mantissa) <= 9,999,999,999,999,999' and
    //:   '-398 <= exponent <= 369'), the 64-bit decimal floating number
    //:   consisting of the mantissa and exponent is returned without rounding.
    //:
    //: 6 The four overloads of 'makeDecimal64' perform properly.
    //:
    //: 7 Note that this test is adapted from the original 'makeDecimal64' test
    //:   in the old 'bdldfp::DecimalImplUtil' component.
    //
    // Plan:
    //: 1 Test that 'makeDecimal64' returns a value that is 'equals' to the
    //:   value given by 'parse64' called on a string containing the specified
    //:   'mantissa' and 'exponent'.
    //:
    //: 2 Test 'makeDecimal64' on values for which both the mantissa and
    //:   exponent are in the range of 64-bit decimal floating point. The value
    //:   returned should be identical in bits to that returned by
    //:   'makeDecimal64Raw' called on 'mantissa' and 'exponent'.
    //:
    //: 3 For each mantissa, exponent pair, test 'makeDecimal64' for all
    //:   overloads for which the mantissa fits.
    //
    // Testing:
    //   makeDecimal64(                   int, int)
    //   makeDecimal64(unsigned           int, int)
    //   makeDecimal64(         long long int, int)
    //   makeDecimal64(unsigned long long int, int)
    // ------------------------------------------------------------------------

    if (verbose) bsl::cout << bsl::endl
                           << "TESTING 'makeDecimal64'" << bsl::endl
                           << "=======================" << bsl::endl;
    {
        for (int mi = 0; mi < NUM_TEST_NONZERO_MANTISSAS; ++mi) {
            if (veryVerbose) cout << endl
                                  << "Testing mantissa index: "
                                  << mi << endl;
            for (int ei = 0; ei < NUM_TEST_EXPONENTS; ++ei) {
                const long long MANTISSA = TEST_NONZERO_MANTISSAS[mi];
                const int EXPONENT = TEST_EXPONENTS[ei];

            if (veryVerbose) cout << endl
                                  << "Testing exponent index: " << ei
                                  << ", MANTISSA: " << MANTISSA
                                  << ", EXPONENT: " << EXPONENT << endl;

                char TEST_STRING[100];
                sprintf(TEST_STRING, "%llde%d", MANTISSA, EXPONENT);

                Util::ValueType64 EXPECTED64 =
                    Util::parse64(TEST_STRING);
                LOOP2_ASSERT(MANTISSA, EXPONENT,
                             Util::equal(Util::makeDecimal64(MANTISSA,
                                                             EXPONENT),
                                         EXPECTED64));

                if (MANTISSA >= 0) {
                    LOOP2_ASSERT(MANTISSA, EXPONENT,
                            Util::equal(Util::makeDecimal64(
                                 static_cast<unsigned long long>(MANTISSA),
                                                                 EXPONENT),
                                        EXPECTED64));
                }
                if ((MANTISSA >= bsl::numeric_limits<int>::min()) &&
                    (MANTISSA <= bsl::numeric_limits<int>::max())) {
                    LOOP2_ASSERT(MANTISSA, EXPONENT,
                                 Util::equal(Util::makeDecimal64(
                                                static_cast<int>(MANTISSA),
                                                                 EXPONENT),
                                             EXPECTED64));
                }
                if ((MANTISSA >=
                               bsl::numeric_limits<unsigned int>::min()) &&
                    (MANTISSA <=
                               bsl::numeric_limits<unsigned int>::max())) {
                    LOOP2_ASSERT(MANTISSA, EXPONENT,
                                 Util::equal(Util::makeDecimal64(
                                       static_cast<unsigned int>(MANTISSA),
                                                                 EXPONENT),
                                             EXPECTED64));
                }

                bool exponentInRange = (EXPONENT >= -398) &&
                                       (EXPONENT <=  369);
                bool mantissaInRange = (MANTISSA >= -9999999999999999LL) &&
                                       (MANTISSA <=  9999999999999999LL);

                if (exponentInRange & mantissaInRange) {
                    LOOP2_ASSERT(MANTISSA, EXPONENT, Util::equal(
                              Util::makeDecimal64(   MANTISSA, EXPONENT),
                              Util::makeDecimalRaw64(MANTISSA, EXPONENT)));
                    if (MANTISSA >= 0) {
                        LOOP2_ASSERT(MANTISSA, EXPONENT, Util::equal(
                            Util::makeDecimal64(
                               static_cast<unsigned long long>(MANTISSA),
                                                               EXPONENT),
                            Util::makeDecimalRaw64(
                               static_cast<unsigned long long>(MANTISSA),
                                                               EXPONENT)));
                    }
                    if ((MANTISSA >= bsl::numeric_limits<int>::min()) &&
                        (MANTISSA <= bsl::numeric_limits<int>::max())) {
                        LOOP2_ASSERT(MANTISSA, EXPONENT, Util::equal(
                            Util::makeDecimal64(
                                   static_cast<int>(MANTISSA), EXPONENT),
                            Util::makeDecimalRaw64(
                                   static_cast<int>(MANTISSA), EXPONENT)));
                    }
                    if ((MANTISSA >=
                         bsl::numeric_limits<unsigned int>::min()) &&
                        (MANTISSA <=
                         bsl::numeric_limits<unsigned int>::max())) {
                        LOOP2_ASSERT(MANTISSA, EXPONENT, Util::equal(
                            Util::makeDecimal64(
                                     static_cast<unsigned int>(MANTISSA),
                                                               EXPONENT),
                            Util::makeDecimalRaw64(
                                     static_cast<unsigned int>(MANTISSA),
                                                               EXPONENT)));
                    }
                }
            }
        }
    }
}

void TestDriver::testCase12()
{
    // ------------------------------------------------------------------------
    // INFINITY CREATION 'makeInfinity64(bool)'
    //
    // Concerns:
    //:  1 'makeInfinity64' should return an infinity value which is positive,
    //:    when passed no arguments.
    //:
    //:  2 'makeInfinity64' should return an infinity value which is positive,
    //:    when passed a 'false' argument.
    //:
    //:  2 'makeInfinity64' should return an infinity value which is negative,
    //:    when passed a 'true' argument.
    //
    // Plan:
    //:  1 call 'makeInfinity' with no arguments.  (C-1)
    //:
    //:  2 call 'makeInfinity' with 'false' argument.  (C-2)
    //:
    //:  3 call 'makeInfinity' with 'true' argument.  (C-3)
    //
    // Testing:
    //   makeInfinity64(bool)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "INFINITY CREATION 'makeInfinity64(bool)'" << endl
                      << "========================================"
                      << endl;

    Util::ValueType64 ninf = Util::parse64("-inf");
    Util::ValueType64 pinf = Util::parse64("+inf");

    Util::ValueType64 test;

    test = Util::makeInfinity64();
    ASSERT(Util::equal(test, pinf));

    test = Util::makeInfinity64(false);
    ASSERT(Util::equal(test, pinf));

    test = Util::makeInfinity64(true);
    ASSERT(Util::equal(test, ninf));
}

void TestDriver::testCase11()
{
    // ------------------------------------------------------------------------
    // PARSING 'parse32', 'parse64', AND 'parse128'
    //
    // Concerns:
    //:  1 Numerical values are parsed and generated correctly.
    //:
    //:  2 Non-numerical state-values are parsed and generated correctly.
    //:
    //:  3 Alternate creation strings work correctly.
    //:
    //:  4 Signs are interpretted correctly.
    //:
    //:  5 That the quanta of the resultant value equals the number of decimal
    //:    places in input string and does exceed the maximum digits necessary
    //:    to differentiate all values of tested decimal type.
    //:
    //:  6 That if the value produced by parsing input string is not exactly
    //:    representable using the maximum digits supported by tested type,
    //:    then the resultant value is rounded according the rounding
    //:    direction.
    //
    // Plan:
    //:  1 Test a series of strings versus their expected values.
    //:
    //:  2 Test the non-numerical state-values by alternate means of
    //:    generation, such as '1.0/0.0' and '0.0/0.0'.
    //:
    //:  3 Using table technique test that tested functions produce the
    //:    expected values having expected decimal class, sign, significand
    //:    and exponent values.  (C5-6).
    //
    // Testing:
    //   parse32 (const char *);
    //   parse64 (const char *);
    //   parse128(const char *);
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "PARSING 'parse32', 'parse64', AND 'parse128'"
              << endl << "============================================"
              << endl;

    // Testing 'parse32 (const char *)'

    {
        Util::ValueType32 value32;
        Util::ValueType32 test32;

        value32 = Util::makeDecimalRaw32(0, 0);

        test32  = Util::parse32("0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e+4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e+4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e+4");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("0e-9");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0e-9");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+0e-9");
        ASSERT(Util::equal(value32, test32));

        value32 = Util::makeDecimalRaw32(1, 0);

        test32  = Util::parse32("1");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+1");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("1e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+1e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("01e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+01e0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("1e-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+1e-0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("1e+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+1e+0");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+10e-001");
        ASSERT(Util::equal(value32, test32));

        value32 = Util::makeDecimalRaw32(8, 42);

        test32  = Util::parse32("8e42");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+8e42");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("8e+42");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("800e40");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("+800e40");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32(".00800e+45");
        ASSERT(Util::equal(value32, test32));

        value32 = Util::makeDecimalRaw32(-7, -33);

        test32  = Util::parse32("-7e-33");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-00007e-0033");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-70000e-37");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-007e-33");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0.7e-32");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-0.0007e-29");
        ASSERT(Util::equal(value32, test32));
        test32  = Util::parse32("-000.000000000000000000000000000000007");
        ASSERT(Util::equal(value32, test32));

        value32 = Util::convertToDecimal32(
                                         Util::divide(Util::parse64("0"),
                                                      Util::parse64("0")));

        test32  = Util::parse32("nan");
        ASSERT(!Util::equal(test32, test32));

        value32 = Util::convertToDecimal32(
                                         Util::divide(Util::parse64("1"),
                                                      Util::parse64("0")));

        test32  = Util::parse32("inf");
        ASSERT(Util::equal(test32, value32));
        test32  = Util::parse32("+inf");
        ASSERT(Util::equal(test32, value32));
        test32  = Util::parse32("inF");
        ASSERT(Util::equal(test32, value32));
        test32  = Util::parse32("+inF");
        ASSERT(Util::equal(test32, value32));
    }

    // Testing 'parse64 (const char *)'

    {
        Util::ValueType64 value64;
        Util::ValueType64 test64;

        value64 = Util::makeDecimalRaw64(0, 0);

        test64  = Util::parse64("0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e+4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e+4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e+4");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("0e-9");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0e-9");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+0e-9");
        ASSERT(Util::equal(value64, test64));

        value64 = Util::makeDecimalRaw64(1, 0);

        test64  = Util::parse64("1");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+1");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("1e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+1e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("01e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+01e0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("1e-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+1e-0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("1e+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+1e+0");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+10e-001");
        ASSERT(Util::equal(value64, test64));

        value64 = Util::makeDecimalRaw64(8, 42);

        test64  = Util::parse64("8e42");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+8e42");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("8e+42");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("800e40");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("+800e40");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64(".00800e+45");
        ASSERT(Util::equal(value64, test64));

        value64 = Util::makeDecimalRaw64(-7, -33);

        test64  = Util::parse64("-7e-33");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-00007e-0033");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-70000e-37");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-007e-33");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0.7e-32");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-0.0007e-29");
        ASSERT(Util::equal(value64, test64));
        test64  = Util::parse64("-000.000000000000000000000000000000007");
        ASSERT(Util::equal(value64, test64));

        value64 = Util::divide(Util::parse64("0"), Util::parse64("0"));

        test64  = Util::parse64("nan");
        ASSERT(!Util::equal(test64, test64));

        value64 = Util::divide(Util::parse64("1"), Util::parse64("0"));

        test64  = Util::parse64("inf");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("+inf");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("inF");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("+inF");
        ASSERT(Util::equal(test64, value64));

        value64 = Util::divide(Util::parse64("-1"), Util::parse64("0"));

        test64  = Util::parse64("-inf");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("-Inf");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("-InF");
        ASSERT(Util::equal(test64, value64));
        test64  = Util::parse64("-inF");
        ASSERT(Util::equal(test64, value64));
    }

    // Testing 'parse128 (const char *)'

    {
        Util::ValueType128 value128;
        Util::ValueType128 test128;

        value128 = Util::makeDecimalRaw128(0, 0);

        test128  = Util::parse128("0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e+4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e+4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e+4");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("0e-9");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0e-9");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+0e-9");
        ASSERT(Util::equal(value128, test128));

        value128 = Util::makeDecimalRaw128(1, 0);

        test128  = Util::parse128("1");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+1");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("1e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+1e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("01e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+01e0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("1e-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+1e-0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("1e+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+1e+0");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+10e-001");
        ASSERT(Util::equal(value128, test128));

        value128 = Util::makeDecimalRaw128(8, 42);

        test128  = Util::parse128("8e42");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+8e42");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("8e+42");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("800e40");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("+800e40");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128(".00800e+45");
        ASSERT(Util::equal(value128, test128));

        value128 = Util::makeDecimalRaw128(-7, -33);

        test128  = Util::parse128("-7e-33");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-00007e-0033");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-70000e-37");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-007e-33");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0.7e-32");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-0.0007e-29");
        ASSERT(Util::equal(value128, test128));
        test128  = Util::parse128("-00.000000000000000000000000000000007");
        ASSERT(Util::equal(value128, test128));

        value128 = Util::divide(Util::parse128("0"), Util::parse128("0"));

        test128  = Util::parse128("nan");
        ASSERT(!Util::equal(test128, test128));

        value128 = Util::divide(Util::parse128("1"), Util::parse128("0"));

        test128  = Util::parse128("inf");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("+inf");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("inF");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("+inF");
        ASSERT(Util::equal(test128, value128));

        value128 = Util::divide(Util::parse128("-1"), Util::parse128("0"));

        test128  = Util::parse128("-inf");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("-Inf");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("-InF");
        ASSERT(Util::equal(test128, value128));
        test128  = Util::parse128("-inF");
        ASSERT(Util::equal(test128, value128));
    }

    {
        static const struct {
            int           d_line;
            const char   *d_input;
            int           d_class;
            int           d_sign;
            unsigned int  d_significand;
            int           d_exponent;
        } DATA[] = {
            { L_, "1",          FP_NORMAL, 1,       1,  0 },
            { L_, "1.2",        FP_NORMAL, 1,      12, -1 },
            { L_, "1.23",       FP_NORMAL, 1,     123, -2 },
            { L_, "1.234",      FP_NORMAL, 1,    1234, -3 },
            { L_, "1.2345",     FP_NORMAL, 1,   12345, -4 },
            { L_, "1.23456",    FP_NORMAL, 1,  123456, -5 },
            { L_, "1.234567",   FP_NORMAL, 1, 1234567, -6 },
            { L_, "1.2345678",  FP_NORMAL, 1, 1234568, -6 },
            { L_, "1.23456789", FP_NORMAL, 1, 1234568, -6 },

            { L_, "123456",     FP_NORMAL, 1,  123456,  0 },
            { L_, "1234567",    FP_NORMAL, 1, 1234567,  0 },
            { L_, "12345678",   FP_NORMAL, 1, 1234568,  1 },
            { L_, "123456789",  FP_NORMAL, 1, 1234568,  2 },

            { L_, "100000000",  FP_NORMAL, 1, 1000000,  2 },
            { L_, "10000000",   FP_NORMAL, 1, 1000000,  1 },
            { L_, "1000000.0",  FP_NORMAL, 1, 1000000,  0 },
            { L_, "100000.00",  FP_NORMAL, 1, 1000000, -1 },
            { L_, "10000.000",  FP_NORMAL, 1, 1000000, -2 },
            { L_, "1000.0000",  FP_NORMAL, 1, 1000000, -3 },
            { L_, "100.00000",  FP_NORMAL, 1, 1000000, -4 },
            { L_, "10.000000",  FP_NORMAL, 1, 1000000, -5 },
            { L_, "1.0000000",  FP_NORMAL, 1, 1000000, -6 },
            { L_, "0.1000000",  FP_NORMAL, 1, 1000000, -7 },
            { L_, "0.0100000",  FP_NORMAL, 1,  100000, -7 },
            { L_, "0.0010000",  FP_NORMAL, 1,   10000, -7 },
            { L_, "0.0001000",  FP_NORMAL, 1,    1000, -7 },
            { L_, "0.0000100",  FP_NORMAL, 1,     100, -7 },
            { L_, "0.0000010",  FP_NORMAL, 1,      10, -7 },
            { L_, "0.0000001",  FP_NORMAL, 1,       1, -7 },
            { L_, "0.00000001", FP_NORMAL, 1,       1, -8 },
        };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int&          LINE            = DATA[ti].d_line;
            const char         *INPUT           = DATA[ti].d_input;
            const int&          EXP_CLASS       = DATA[ti].d_class;
            const int&          EXP_SIGN        = DATA[ti].d_sign;
            const unsigned int& EXP_SIGNIFICAND = DATA[ti].d_significand;
            const int&          EXP_EXPONENT    = DATA[ti].d_exponent;

            int           SIGN;
            unsigned int  SIGNIFICAND;
            int           EXPONENT;

            const Util::ValueType32 RESULT = Util::parse32(INPUT);

            const int CLASS = Util::decompose(&SIGN,
                                              &SIGNIFICAND,
                                              &EXPONENT,
                                              RESULT);

            LOOP3_ASSERT(LINE, CLASS, EXP_CLASS, CLASS == EXP_CLASS);

            LOOP3_ASSERT(LINE, SIGN,          EXP_SIGN,
                               SIGN        == EXP_SIGN);
            LOOP3_ASSERT(LINE, SIGNIFICAND,   EXP_SIGNIFICAND,
                               SIGNIFICAND == EXP_SIGNIFICAND);
            LOOP3_ASSERT(LINE, EXPONENT,      EXP_EXPONENT,
                               EXPONENT    == EXP_EXPONENT);
        }
    }
    {
        typedef bsls::Types::Uint64 UINT_64;

        static const struct {
            int         d_line;
            const char *d_input;
            UINT_64     d_significand;
            int         d_exponent;
        } DATA[] = {
        //------------------------------------------------------------
        // LINE | INPUT               | SIGNFICAND        | EXPONENT
        //------------------------------------------------------------
            { L_, "1",                                 1ll,        0 },
            { L_, "1.2",                              12ll,       -1 },
            { L_, "1.234",                          1234ll,       -3 },
            { L_, "1.23456",                      123456ll,       -5 },
            { L_, "1.2345678",                  12345678ll,       -7 },
            { L_, "1.234567890",              1234567890ll,       -9 },
            { L_, "1.23456789012",          123456789012ll,      -11 },
            { L_, "1.2345678901234",      12345678901234ll,      -13 },
            { L_, "1.234567890123456",  1234567890123456ll,      -15 },
            { L_, "1.2345678901234567", 1234567890123457ll,      -15 },

            { L_, "123456789012345",     123456789012345ll,        0 },
            { L_, "1234567890123456",   1234567890123456ll,        0 },
            { L_, "12345678901234567",  1234567890123457ll,        1 },
            { L_, "123456789012345678", 1234567890123457ll,        2 },

            { L_, "100000000000000000", 1000000000000000ll,        2 },
            { L_, "10000000000000000",  1000000000000000ll,        1 },
            { L_, "1000000000000000",   1000000000000000ll,        0 },
            { L_, "100000000000000.0",  1000000000000000ll,       -1 },
            { L_, "10000000000000.00",  1000000000000000ll,       -2 },
            { L_, "10.00000000000000",  1000000000000000ll,      -14 },
            { L_, "1.000000000000000",  1000000000000000ll,      -15 },
            { L_, "0.100000000000000",   100000000000000ll,      -15 },
            { L_, "0.010000000000000",    10000000000000ll,      -15 },
            { L_, "0.000000000000100",               100ll,      -15 },
            { L_, "0.000000000000010",                10ll,      -15 },
            { L_, "0.000000000000001",                 1ll,      -15 },
            { L_, "0.0000000000000001",                1ll,      -16 },
        };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int&     LINE            = DATA[ti].d_line;
            const char    *INPUT           = DATA[ti].d_input;
            const UINT_64& EXP_SIGNIFICAND = DATA[ti].d_significand;
            const int&     EXP_EXPONENT    = DATA[ti].d_exponent;

            int      SIGN;
            UINT_64  SIGNIFICAND;
            int      EXPONENT;

            const Util::ValueType64 RESULT = Util::parse64(INPUT);

            const int CLASS = Util::decompose(&SIGN,
                                              &SIGNIFICAND,
                                              &EXPONENT,
                                              RESULT);

            LOOP2_ASSERT(LINE, CLASS, CLASS == FP_NORMAL);

            LOOP2_ASSERT(LINE, SIGN, SIGN  == 1);
            LOOP3_ASSERT(LINE, SIGNIFICAND,   EXP_SIGNIFICAND,
                               SIGNIFICAND == EXP_SIGNIFICAND);
            LOOP3_ASSERT(LINE, EXPONENT,      EXP_EXPONENT,
                               EXPONENT    == EXP_EXPONENT);
        }
    }

    {
        static const struct {
            int         d_line;
            const char *d_input;
            int         d_exponent;
        } DATA[] = {
        //---------------------------------------------------------
        // LINE | INPUT                                 | EXPONENT
        //---------------------------------------------------------
            { L_, "100000000000000000000000000000000000",      2 },
            { L_, "10000000000000000000000000000000000",       1 },
            { L_, "1000000000000000000000000000000000",        0 },
            { L_, "100000000000000000000000000000000.0",      -1 },
            { L_, "10000000000000000000000000000000.00",      -2 },
            { L_, "10.00000000000000000000000000000000",     -32 },
            { L_, "1.000000000000000000000000000000000",     -33 },
            { L_, "0.100000000000000000000000000000000",     -33 },
            { L_, "0.010000000000000000000000000000000",     -33 },
            { L_, "0.001000000000000000000000000000000",     -33 },
            { L_, "0.000000000000000000000000000000010",     -33 },
            { L_, "0.000000000000000000000000000000001",     -33 },
            { L_, "0.0000000000000000000000000000000001",    -34 },
        };

        const int NUM_DATA = static_cast<int>(sizeof DATA / sizeof *DATA);

        for (int ti = 0; ti < NUM_DATA; ++ti) {
            const int&     LINE            = DATA[ti].d_line;
            const char    *INPUT           = DATA[ti].d_input;
            const int&     EXP_EXPONENT    = DATA[ti].d_exponent;

            int            SIGN;
            BDEC::Uint128  SIGNIFICAND;
            int            EXPONENT;

            const Util::ValueType128 RESULT = Util::parse128(INPUT);

            const int CLASS = Util::decompose(&SIGN,
                                              &SIGNIFICAND,
                                              &EXPONENT,
                                              RESULT);

            LOOP2_ASSERT(LINE, CLASS, CLASS == FP_NORMAL);

            LOOP2_ASSERT(LINE, SIGN, SIGN == 1);
            LOOP3_ASSERT(LINE, EXPONENT,     EXP_EXPONENT,
                               EXPONENT   == EXP_EXPONENT);
        }
    }
}

void TestDriver::testCase10()
{
    // ------------------------------------------------------------------------
    // CROSS CONVERSION 'convertToDecimalXX'
    //
    // Concerns:
    //:  1 Post-conversion, the value should be as expected.
    //:
    //:  2 Rounded values should become infinity or 0 when truncating.
    //:
    //:  3 NaN value-states should convert correctly.
    //
    // Plan:
    //:  1 Convert some values to wider types, and confirm the value is as
    //:    expected.
    //:
    //:  2 Convert some values to narrower types, and confirm the value is
    //:    preserved or truncated as appropriate.
    //:
    //:  3 Convert NaN states using all functions
    //
    // Testing:
    //   convertToDecimal32( const ValueType128&)
    //   convertToDecimal32( const ValueType64&)
    //   convertToDecimal64( const ValueType32&)
    //   convertToDecimal64( const ValueType128&)
    //   convertToDecimal128(const ValueType32&)
    //   convertToDecimal128(const ValueType64&)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "CROSS CONVERSION 'convertToDecimalXX'" << endl
                      << "=====================================" << endl;

    // Testing 'convertToDecimal32( const ValueType64&)'

    {
        Util::ValueType32  test32;
        Util::ValueType32 value32;

         errno  = 0;
         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64(  0,   0));
        value32 = Util::makeDecimalRaw32(                         0,   0);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64( 42,   0));
        value32 = Util::makeDecimalRaw32(                        42,   0);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64(-42,   0));
        value32 = Util::makeDecimalRaw32(                       -42,   0);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64( 42,   4));
        value32 = Util::makeDecimalRaw32(                        42,   4);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64(-42,   4));
        value32 = Util::makeDecimalRaw32(                       -42,   4);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64( 42, -17));
        value32 = Util::makeDecimalRaw32(                        42, -17);
        ASSERT(Util::equal(test32, value32));

         test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw64(-42, -17));
        value32 = Util::makeDecimalRaw32(                       -42, -17);
        ASSERT(Util::equal(test32, value32));

        ASSERT(0 == errno);

        test32  = Util::convertToDecimal32(
                                   Util::makeDecimalRaw64( 1048576,  300));
        value32 = Util::parse32("Inf");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno   = 0;
        test32  = Util::convertToDecimal32(
                                   Util::makeDecimalRaw64(-1048576,  300));
        value32 = Util::parse32("-Inf");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno   = 0;
        test32  = Util::convertToDecimal32(
                                   Util::makeDecimalRaw64( 1048576, -300));
        value32 = Util::parse32("0");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno   = 0;
        test32  = Util::convertToDecimal32(
                                   Util::makeDecimalRaw64(-1048576, -300));
        value32 = Util::parse32("-0");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        test32  = Util::convertToDecimal32(Util::parse64("NaN"));
        ASSERT(!Util::equal(test32, test32));

        errno   = 0;
        test32  = Util::convertToDecimal32(Util::parse64("sNaN"));
        ASSERT(!Util::equal(test32, test32));
        ASSERT(EDOM == errno);
    }

    // Testing 'convertToDecimal32( const ValueType128&)'

    {
        Util::ValueType32  test32;
        Util::ValueType32 value32;

        errno  = 0;
        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128(  0,   0));
        value32 = Util::makeDecimalRaw32(                          0,   0);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128( 42,   0));
        value32 = Util::makeDecimalRaw32(                         42,   0);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128(-42,   0));
        value32 = Util::makeDecimalRaw32(                        -42,   0);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128( 42,   4));
        value32 = Util::makeDecimalRaw32(                         42,   4);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128(-42,   4));
        value32 = Util::makeDecimalRaw32(                        -42,   4);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128( 42, -17));
        value32 = Util::makeDecimalRaw32(                         42, -17);
        ASSERT(Util::equal(test32, value32));

        test32 = Util::convertToDecimal32(
                                         Util::makeDecimalRaw128(-42, -17));
        value32 = Util::makeDecimalRaw32(                        -42, -17);
        ASSERT(Util::equal(test32, value32));

        ASSERT(0 == errno);

        test32 = Util::convertToDecimal32(
                                   Util::makeDecimalRaw128( 1048576,  300));
        value32 = Util::parse32("Inf");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno  = 0;
        test32 = Util::convertToDecimal32(
                                   Util::makeDecimalRaw128(-1048576,  300));
        value32 = Util::parse32("-Inf");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno  = 0;
        test32 = Util::convertToDecimal32(
                                   Util::makeDecimalRaw128( 1048576, -300));
        value32 = Util::parse32("0");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);

        errno  = 0;
        test32 = Util::convertToDecimal32(
                                   Util::makeDecimalRaw128(-1048576, -300));
        value32 = Util::parse32("-0");
        ASSERT(Util::equal(test32, value32));
        ASSERT(ERANGE == errno);


        test32 = Util::convertToDecimal32(Util::parse128("NaN"));
        ASSERT(!Util::equal(test32, test32));
    }

    // Testing 'convertToDecimal64( const ValueType32&)'

    {
        Util::ValueType64  test64;
        Util::ValueType64 value64;

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32(  0,   0));
        value64 = Util::makeDecimalRaw64(                         0,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32( 42,   0));
        value64 = Util::makeDecimalRaw64(                        42,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32(-42,   0));
        value64 = Util::makeDecimalRaw64(                       -42,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32( 42,   4));
        value64 = Util::makeDecimalRaw64(                        42,   4);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32(-42,   4));
        value64 = Util::makeDecimalRaw64(                       -42,   4);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32( 42, -17));
        value64 = Util::makeDecimalRaw64(                        42, -17);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                         Util::makeDecimalRaw32(-42, -17));
        value64 = Util::makeDecimalRaw64(                       -42, -17);
        ASSERT(Util::equal(test64, value64));

                    // Infinities and 0 rounding are not possible with
                    // widening conversions, so we only test for 'NaN'
                    // preservation.

         test64 = Util::convertToDecimal64(Util::parse32("NaN"));
        ASSERT(!Util::equal(test64, test64));
    }

    // Testing 'convertToDecimal64( const ValueType128&)'

    {
        Util::ValueType64  test64;
        Util::ValueType64 value64;

         errno  = 0;
         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128(  0,   0));
        value64 = Util::makeDecimalRaw64(                         0,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128( 42,   0));
        value64 = Util::makeDecimalRaw64(                        42,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128(-42,   0));
        value64 = Util::makeDecimalRaw64(                       -42,   0);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128( 42,   4));
        value64 = Util::makeDecimalRaw64(                        42,   4);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128(-42,   4));
        value64 = Util::makeDecimalRaw64(                       -42,   4);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128( 42, -17));
        value64 = Util::makeDecimalRaw64(                        42, -17);
        ASSERT(Util::equal(test64, value64));

         test64 = Util::convertToDecimal64(
                                        Util::makeDecimalRaw128(-42, -17));
        value64 = Util::makeDecimalRaw64(                       -42, -17);
        ASSERT(Util::equal(test64, value64));

        ASSERT(0 == errno);

         test64 = Util::convertToDecimal64(
                                 Util::makeDecimalRaw128( 1048576,  6000));
        value64 = Util::parse64("Inf");
        ASSERT(Util::equal(test64, value64));
        ASSERT(ERANGE == errno);

         errno  = 0;
         test64 = Util::convertToDecimal64(
                                 Util::makeDecimalRaw128(-1048576,  6000));
        value64 = Util::parse64("-Inf");
        ASSERT(Util::equal(test64, value64));
        ASSERT(ERANGE == errno);

         errno  = 0;
         test64 = Util::convertToDecimal64(
                                 Util::makeDecimalRaw128( 1048576, -6000));
        value64 = Util::parse64("0");
        ASSERT(Util::equal(test64, value64));
        ASSERT(ERANGE == errno);

         errno  = 0;
         test64 = Util::convertToDecimal64(
                                 Util::makeDecimalRaw128(-1048576, -6000));
        value64 = Util::parse64("-0");
        ASSERT(Util::equal(test64, value64));
        ASSERT(ERANGE == errno);

         test64 = Util::convertToDecimal64(Util::parse128("NaN"));
        ASSERT(!Util::equal(test64, test64));
    }

    // Testing 'convertToDecimal128(const ValueType32&)'

    {
        Util::ValueType128  test128;
        Util::ValueType128 value128;

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32(  0,   0));
        value128 = Util::makeDecimalRaw128(                       0,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32( 42,   0));
        value128 = Util::makeDecimalRaw128(                      42,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32(-42,   0));
        value128 = Util::makeDecimalRaw128(                     -42,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32( 42,   4));
        value128 = Util::makeDecimalRaw128(                      42,   4);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32(-42,   4));
        value128 = Util::makeDecimalRaw128(                     -42,   4);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32( 42, -17));
        value128 = Util::makeDecimalRaw128(                      42, -17);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw32(-42, -17));
        value128 = Util::makeDecimalRaw128(                     -42, -17);
        ASSERT(Util::equal(test128, value128));

                    // Infinities and 0 rounding are not possible with
                    // widening conversions, so we only test for 'NaN'
                    // preservation.

         test128 = Util::convertToDecimal128(Util::parse32("NaN"));
        ASSERT(!Util::equal(test128, test128));
    }

    // Testing 'convertToDecimal128(const ValueType64&)'

    {
        Util::ValueType128  test128;
        Util::ValueType128 value128;

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64(  0,   0));
        value128 = Util::makeDecimalRaw128(                       0,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64( 42,   0));
        value128 = Util::makeDecimalRaw128(                      42,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64(-42,   0));
        value128 = Util::makeDecimalRaw128(                     -42,   0);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64( 42,   4));
        value128 = Util::makeDecimalRaw128(                      42,   4);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64(-42,   4));
        value128 = Util::makeDecimalRaw128(                     -42,   4);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64( 42, -17));
        value128 = Util::makeDecimalRaw128(                      42, -17);
        ASSERT(Util::equal(test128, value128));

         test128 = Util::convertToDecimal128(
                                         Util::makeDecimalRaw64(-42, -17));
        value128 = Util::makeDecimalRaw128(                     -42, -17);
        ASSERT(Util::equal(test128, value128));

                    // Infinities and 0 rounding are not possible with
                    // widening conversions, so we only test for 'NaN'
                    // preservation.

         test128 = Util::convertToDecimal128(Util::parse64("NaN"));
        ASSERT(!Util::equal(test128, test128));
    }
}

void TestDriver::testCase9()
{
    // ------------------------------------------------------------------------
    // ARITHMETIC FUNCTION 'negate'
    //
    // Concerns:
    //:  1 'negate' returns the correct answer.
    //:
    //:  2 'negate' inverts signed 0 values.
    //:
    //:  3 'negate' inverts 'Inf' state-values.
    //:
    //
    // Plan:
    //:  1 Test several example values for negation and equality. (C-1..3)
    //
    // Testing:
    //   negate(ValueType32)
    //   negate(ValueType64)
    //   negate(ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "ARITHMETIC FUNCTION 'negate'" << endl
                      << "============================" << endl;

    Util::ValueType32 nZero32 = Util::parse32("-0");
    Util::ValueType32 pZero32 = Util::parse32("+0");

    Util::ValueType32 nFive32 = Util::parse32("-5");
    Util::ValueType32 pFive32 = Util::parse32("+5");

    Util::ValueType32 nSeventeen32 = Util::parse32("-17");
    Util::ValueType32 pSeventeen32 = Util::parse32("+17");

    ASSERT(Util::equal(pZero32, Util::negate(nZero32)));
    ASSERT(Util::equal(nZero32, Util::negate(pZero32)));

    // Check for zero sign correctly...

    {
        Util::ValueType32 tmp = Util::negate(pZero32);
        ASSERT(!bsl::memcmp(&nZero32, &tmp, sizeof(tmp)));

        tmp = Util::negate(nZero32);
        ASSERT(!bsl::memcmp(&pZero32, &tmp, sizeof(tmp)));
    }

    ASSERT(Util::equal(pFive32, Util::negate(nFive32)));
    ASSERT(Util::equal(nFive32, Util::negate(pFive32)));

    ASSERT(Util::equal(pSeventeen32, Util::negate(nSeventeen32)));
    ASSERT(Util::equal(nSeventeen32, Util::negate(pSeventeen32)));

    Util::ValueType64 nZero64 = Util::parse64("-0");
    Util::ValueType64 pZero64 = Util::parse64("+0");

    Util::ValueType64 nFive64 = Util::parse64("-5");
    Util::ValueType64 pFive64 = Util::parse64("+5");

    Util::ValueType64 nSeventeen64 = Util::parse64("-17");
    Util::ValueType64 pSeventeen64 = Util::parse64("+17");

    ASSERT(Util::equal(pZero64, Util::negate(nZero64)));
    ASSERT(Util::equal(nZero64, Util::negate(pZero64)));

    // Check for zero sign correctly...

    {
        Util::ValueType64 tmp = Util::negate(pZero64);
        ASSERT(!bsl::memcmp(&nZero64, &tmp, sizeof(tmp)));

        tmp = Util::negate(nZero64);
        ASSERT(!bsl::memcmp(&pZero64, &tmp, sizeof(tmp)));
    }

    ASSERT(Util::equal(pFive64, Util::negate(nFive64)));
    ASSERT(Util::equal(nFive64, Util::negate(pFive64)));

    ASSERT(Util::equal(pSeventeen64, Util::negate(nSeventeen64)));
    ASSERT(Util::equal(nSeventeen64, Util::negate(pSeventeen64)));

    Util::ValueType128 nZero128 = Util::parse128("-0");
    Util::ValueType128 pZero128 = Util::parse128("+0");

    Util::ValueType128 nFive128 = Util::parse128("-5");
    Util::ValueType128 pFive128 = Util::parse128("+5");

    Util::ValueType128 nSeventeen128 = Util::parse128("-17");
    Util::ValueType128 pSeventeen128 = Util::parse128("+17");

    ASSERT(Util::equal(pZero128, Util::negate(nZero128)));
    ASSERT(Util::equal(nZero128, Util::negate(pZero128)));

    // Check for zero sign correctly...

    {
        Util::ValueType128 tmp = Util::negate(pZero128);
        ASSERT(!bsl::memcmp(&nZero128, &tmp, sizeof(tmp)));

        tmp = Util::negate(nZero128);
        ASSERT(!bsl::memcmp(&pZero128, &tmp, sizeof(tmp)));
    }

    ASSERT(Util::equal(pFive128, Util::negate(nFive128)));
    ASSERT(Util::equal(nFive128, Util::negate(pFive128)));

    ASSERT(Util::equal(pSeventeen128, Util::negate(nSeventeen128)));
    ASSERT(Util::equal(nSeventeen128, Util::negate(pSeventeen128)));
}

void TestDriver::testCase8()
{
    // ------------------------------------------------------------------------
    // ARITHMETIC FUNCTION 'divide'
    //
    // Concerns:
    //:  1 'divide' should never (except in identity, 'NaN' and 'Inf' cases)
    //:    cases) return the same value as at least one of the operands.
    //:
    //:  2 'divide' behaves correctly with identity operand (1).
    //:
    //:  3 'divide' will return a distinct value from both of its operands,
    //:    when both are non-zero and value-states (not 'NaN' or 'Inf').
    //:
    //:  4 'divide' to 'NaN' or 'Inf' should follow the IEEE rules for the
    //:    cases listed in this chart:
    //:
    //:             L / R|-Inf|Normal|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:             -Inf | NaN|+/-Inf| NaN|NaN|
    //:            ------+----+------+----+---+
    //:            Normal|+/-0|Normal|+/-0|NaN|
    //:            ------+----+------+----+---+
    //:             +Inf | NaN|+/-Inf| NaN|NaN|
    //:            ------+----+------+----+---+
    //:              NaN | NaN|  NaN | NaN|NaN|
    //:
    //:  5 'divide' behaves reasonably when working with different quanta.
    //:
    //:  6 'divide' by 0 gives a 'NaN'.
    //
    // Plan:
    //:  1 Test a handful of expected values of different exponent and
    //:    mantissa, with both possible orders. (C-1,5,6)
    //:
    //:  2 Test identity with '1' case. (C-2)
    //:
    //:  3 When not dealing with special cases (or rounding cases), make sure
    //:    the result value does not compare equal to either source.  (C-3)
    //:
    //:  4 Test all 16 special cases in the chart, which covers both orders.
    //:    (C-4,6)
    //
    // Testing:
    //   divide(ValueType32,  ValueType32)
    //   divide(ValueType64,  ValueType64)
    //   divide(ValueType128, ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "ARITHMETIC FUNCTION 'divide'" << endl
                      << "============================" << endl;

    Util::ValueType32     lhs32;
    Util::ValueType32     rhs32;
    Util::ValueType32  result32;

    Util::ValueType64     lhs64;
    Util::ValueType64     rhs64;
    Util::ValueType64  result64;

    Util::ValueType128    lhs128;
    Util::ValueType128    rhs128;
    Util::ValueType128 result128;

    struct  {
        long long int lhsMantissa;
                  int lhsExponent;
        long long int rhsMantissa;
                  int rhsExponent;
        long long int resMantissa;
                  int resExponent;
    } testCases[] = {
        {  0,  0,  1,  0,  0,  0 },
        {  1,  0,  1,  0,  1,  0 },
        {  1,  0,  1,  0,  1,  0 },
        { 42,  0,  1,  0, 42,  0 },
        {  1,  0, 10,  0, 10, -2 },
        { 42,  0,  1,  1, 42, -1 },
        {  1,  1, 10,  0, 10, -1 },
        { 42,  0,  1,  2, 42, -2 },
        {  1,  2, 10,  0, 10,  0 }
    };
    const int numTestCases = static_cast<int>(
                                       sizeof(testCases) / sizeof(*testCases));

    for (int i = 0; i < numTestCases; ++i) {
        long long int lhsMantissa = testCases[ i ].lhsMantissa;
                  int lhsExponent = testCases[ i ].lhsExponent;
        long long int rhsMantissa = testCases[ i ].rhsMantissa;
                  int rhsExponent = testCases[ i ].rhsExponent;
        long long int resMantissa = testCases[ i ].resMantissa;
                  int resExponent = testCases[ i ].resExponent;

        if (veryVerbose) cout << endl
                              << "Test 'divide(ValueType32,"
                              << "  ValueType32)', " << endl
                              << "     'divide(ValueType64,"
                              << "  ValueType64)' and" << endl
                              << "     'divide(ValueType128,"
                              << " ValueType128)' on" << endl
                              << lhsMantissa << "e" << lhsExponent
                              << " / "
                              << rhsMantissa << "e" << rhsExponent
                              << " == "
                              << resMantissa << "e" << resExponent << endl;

        Util::ValueType32 identity32 = Util::parse32("1");

        lhs32 = Util::makeDecimalRaw32(static_cast<int>(lhsMantissa),
                                                        lhsExponent);
        rhs32 = Util::makeDecimalRaw32(static_cast<int>(rhsMantissa),
                                                        rhsExponent);
        result32 = Util::divide(lhs32, rhs32);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(
                        result32,
                        Util::makeDecimalRaw32(static_cast<int>(resMantissa),
                                                                resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(lhs32, Util::divide(lhs32, identity32)));

        Util::ValueType64 identity64 = Util::parse64("1");

           lhs64 = Util::makeDecimalRaw64(lhsMantissa, lhsExponent);
           rhs64 = Util::makeDecimalRaw64(rhsMantissa, rhsExponent);
        result64 = Util::divide(lhs64, rhs64);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result64, Util::makeDecimalRaw64(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs64, Util::divide(lhs64, identity64)));


        Util::ValueType128 identity128 = Util::parse128("1");

           lhs128 = Util::makeDecimalRaw128(lhsMantissa, lhsExponent);
           rhs128 = Util::makeDecimalRaw128(rhsMantissa, rhsExponent);
        result128 = Util::divide(lhs128, rhs128);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result128, Util::makeDecimalRaw128(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs128, Util::divide(lhs128,
                                                  identity128)));
    }


                    // Testing for 'NaN'/'Inf' special cases:
    {
        //:             L / R|-Inf|Normal|+Inf|NaN|Zero|
        //:            ------+----+------+----+---+----+
        //:             -Inf | NaN|+/-Inf| NaN|NaN|-Inf|
        //:            ------+----+------+----+---+----+
        //:            Normal|+/-0|Normal|+/-0|NaN| Inf|
        //:            ------+----+------+----+---+----+
        //:             +Inf | NaN|+/-Inf| NaN|NaN| Inf|
        //:            ------+----+------+----+---+----+
        //:              NaN | NaN|  NaN | NaN|NaN| NaN|
        //:            ------+----+------+----+---+----+
        //:             Zero |+/-0| +/-0 |+/-0|NaN| NaN|

        Util::ValueType32   ninf32 = Util::parse32("-Inf");
        Util::ValueType32   pinf32 = Util::parse32("+Inf");
        Util::ValueType32    nan32 = Util::parse32( "NaN");
        Util::ValueType32   snan32 = Util::parse32("sNaN");
        Util::ValueType32   zero32 = Util::parse32(   "0");
        Util::ValueType32 normal32 = Util::makeDecimalRaw32(42, 1);

        ASSERT(nanEqual( nan32, Util::divide(  ninf32,   ninf32)));
        ASSERT(nanEqual(ninf32, Util::divide(  ninf32, normal32)));
        ASSERT(nanEqual( nan32, Util::divide(  ninf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::divide(  ninf32,    nan32)));
        ASSERT(nanEqual(ninf32, Util::divide(  ninf32,   zero32)));

        ASSERT(nanEqual(zero32, Util::divide(normal32,   ninf32)));
        ASSERT(nanEqual(        Util::divide(normal32, normal32),
                        Util::makeDecimalRaw32(1, 0)));
        ASSERT(nanEqual(zero32, Util::divide(normal32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::divide(normal32,    nan32)));
        ASSERT(nanEqual(pinf32, Util::divide(normal32,   zero32)));

        ASSERT(nanEqual( nan32, Util::divide(  pinf32,   ninf32)));
        ASSERT(nanEqual(pinf32, Util::divide(  pinf32, normal32)));
        ASSERT(nanEqual( nan32, Util::divide(  pinf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::divide(  pinf32,    nan32)));
        ASSERT(nanEqual(pinf32, Util::divide(  pinf32,   zero32)));

        ASSERT(nanEqual( nan32, Util::divide(   nan32,   ninf32)));
        ASSERT(nanEqual( nan32, Util::divide(   nan32, normal32)));
        ASSERT(nanEqual( nan32, Util::divide(   nan32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::divide(   nan32,    nan32)));
        ASSERT(nanEqual( nan32, Util::divide(   nan32,   zero32)));

        ASSERT(nanEqual(zero32, Util::divide(  zero32,   ninf32)));
        ASSERT(nanEqual(zero32, Util::divide(  zero32, normal32)));
        ASSERT(nanEqual(zero32, Util::divide(  zero32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::divide(  zero32,    nan32)));
        ASSERT(nanEqual( nan32, Util::divide(  zero32,   zero32)));

        errno = 0;
        ASSERT(nanEqual( nan32, Util::divide(  snan32,   snan32)));
        ASSERT(EDOM == errno);

        Util::ValueType64   ninf64 = Util::parse64("-Inf");
        Util::ValueType64   pinf64 = Util::parse64("+Inf");
        Util::ValueType64    nan64 = Util::parse64( "NaN");
        Util::ValueType64   snan64 = Util::parse64("sNaN");
        Util::ValueType64   zero64 = Util::parse64(   "0");
        Util::ValueType64 normal64 = Util::makeDecimalRaw64(42, 1);

        ASSERT(nanEqual( nan64, Util::divide(  ninf64,   ninf64)));
        ASSERT(nanEqual(ninf64, Util::divide(  ninf64, normal64)));
        ASSERT(nanEqual( nan64, Util::divide(  ninf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::divide(  ninf64,    nan64)));

        ASSERT(nanEqual(zero64, Util::divide(normal64,   ninf64)));
        ASSERT(nanEqual(        Util::divide(normal64, normal64),
                        Util::makeDecimalRaw64(1, 0)));
        ASSERT(nanEqual(zero64, Util::divide(normal64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::divide(normal64,    nan64)));

        ASSERT(nanEqual( nan64, Util::divide(  pinf64,   ninf64)));
        ASSERT(nanEqual(pinf64, Util::divide(  pinf64, normal64)));
        ASSERT(nanEqual( nan64, Util::divide(  pinf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::divide(  pinf64,    nan64)));

        ASSERT(nanEqual( nan64, Util::divide(   nan64,   ninf64)));
        ASSERT(nanEqual( nan64, Util::divide(   nan64, normal64)));
        ASSERT(nanEqual( nan64, Util::divide(   nan64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::divide(   nan64,    nan64)));

        ASSERT(nanEqual(zero64, Util::divide(  zero64,   ninf64)));
        ASSERT(nanEqual(zero64, Util::divide(  zero64, normal64)));
        ASSERT(nanEqual(zero64, Util::divide(  zero64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::divide(  zero64,    nan64)));
        ASSERT(nanEqual( nan64, Util::divide(  zero64,   zero64)));

        errno = 0;
        ASSERT(nanEqual( nan64, Util::divide(  snan64,   snan64)));
        ASSERT(EDOM == errno);

        Util::ValueType128   ninf128 = Util::parse128("-Inf");
        Util::ValueType128   pinf128 = Util::parse128("+Inf");
        Util::ValueType128    nan128 = Util::parse128( "NaN");
        Util::ValueType128   snan128 = Util::parse128("sNaN");
        Util::ValueType128   zero128 = Util::parse128(   "0");
        Util::ValueType128 normal128 = Util::makeDecimalRaw128(42,1);

        ASSERT(nanEqual( nan128, Util::divide(  ninf128,   ninf128)));
        ASSERT(nanEqual(ninf128, Util::divide(  ninf128, normal128)));
        ASSERT(nanEqual( nan128, Util::divide(  ninf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::divide(  ninf128,    nan128)));

        ASSERT(nanEqual(zero128, Util::divide(normal128,   ninf128)));
        ASSERT(nanEqual(         Util::divide(normal128, normal128),
                        Util::makeDecimalRaw128(1, 0)));
        ASSERT(nanEqual(zero128, Util::divide(normal128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::divide(normal128,    nan128)));

        ASSERT(nanEqual( nan128, Util::divide(  pinf128,   ninf128)));
        ASSERT(nanEqual(pinf128, Util::divide(  pinf128, normal128)));
        ASSERT(nanEqual( nan128, Util::divide(  pinf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::divide(  pinf128,    nan128)));

        ASSERT(nanEqual( nan128, Util::divide(   nan128,   ninf128)));
        ASSERT(nanEqual( nan128, Util::divide(   nan128, normal128)));
        ASSERT(nanEqual( nan128, Util::divide(   nan128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::divide(   nan128,    nan128)));

        errno = 0;
        ASSERT(nanEqual( nan128, Util::divide(  snan128,   snan128)));
        ASSERT(EDOM == errno);

        // Zero checks:

        ASSERT(nanEqual( nan128, Util::divide(  zero128, zero128)));
        ASSERT(nanEqual(pinf128, Util::divide(normal128, zero128)));
        ASSERT(nanEqual(ninf128,
                   Util::divide(Util::makeDecimalRaw128(-1, 0), zero128)));
    }
}

void TestDriver::testCase7()
{
    // ------------------------------------------------------------------------
    // ARITHMETIC FUNCTION 'multiply'
    //
    // Concerns:
    //:  1 'multiply' should never (except in identity, 'NaN' and 'Inf' cases)
    //:    return the same value as at least one of the operands.
    //:
    //:  2 'multiply' behaves correctly with identity operand (1).
    //:
    //:  3 'multiply' will return a distinct value from both of its operands,
    //:    when both are non-zero and value-states (not 'NaN' or 'Inf').
    //:
    //:  4 'multiply' to 'NaN' or 'Inf' should follow the IEEE rules for the
    //:    cases listed in this chart:
    //:
    //:             L * R|-Inf|Normal|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:             -Inf |+Inf|+/-Inf|-Inf|NaN|
    //:            ------+----+------+----+---+
    //:            Normal| Inf|Normal| Inf|NaN|
    //:            ------+----+------+----+---+
    //:             +Inf |-Inf|+/-Inf|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:              NaN | NaN|  NaN | NaN|NaN|
    //:
    //:  5 'multiply' behaves reasonably when working with different quanta.
    //:
    //:  6 'multiply' by 0 behaves as expected.
    //
    // Plan:
    //:  1 Test a handful of expected values of different exponent and
    //:    mantissa, with both possible orders. (C-1,5,6)
    //:
    //:  2 Test identity with '1' case. (C-2)
    //:
    //:  3 When not dealing with special cases (or rounding cases), make sure
    //:    the result value does not compare equal to either source. (C-3)
    //:
    //:  4 Test all 16 special cases in the chart, which covers both
    //:    orders. (C-4,6)
    //
    // Testing:
    //   multiply(ValueType32,  ValueType32)
    //   multiply(ValueType64,  ValueType64)
    //   multiply(ValueType128, ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "ARITHMETIC FUNCTION 'multiply'" << endl
                      << "==============================" << endl;

    Util::ValueType32     lhs32;
    Util::ValueType32     rhs32;
    Util::ValueType32  result32;

    Util::ValueType64     lhs64;
    Util::ValueType64     rhs64;
    Util::ValueType64  result64;

    Util::ValueType128    lhs128;
    Util::ValueType128    rhs128;
    Util::ValueType128 result128;

    struct  {
        long long int lhsMantissa;
                  int lhsExponent;
        long long int rhsMantissa;
                  int rhsExponent;
        long long int resMantissa;
                  int resExponent;
    } testCases[] = {
        {  0,  0,  0,  0,  0,  0 },
        {  1,  0,  0,  0,  0,  0 },
        {  0,  0,  1,  0,  0,  0 },
        {  1,  0,  1,  0,  1,  0 },
        {  1,  0,  1,  0,  1,  0 },
        { 42,  0,  1,  0, 42,  0 },
        {  1,  0, 42,  0, 42,  0 },
        { 42,  0,  1,  1, 42,  1 },
        {  1,  1, 42,  0, 42,  1 },
        { 42,  0,  1,  2, 42,  2 },
        {  1,  2, 42,  0, 42,  2 }
    };
    const int numTestCases = static_cast<int>(sizeof(testCases) /
                                              sizeof(*testCases));

    for (int i = 0; i < numTestCases; ++i) {
        long long int lhsMantissa = testCases[ i ].lhsMantissa;
                  int lhsExponent = testCases[ i ].lhsExponent;
        long long int rhsMantissa = testCases[ i ].rhsMantissa;
                  int rhsExponent = testCases[ i ].rhsExponent;
        long long int resMantissa = testCases[ i ].resMantissa;
                  int resExponent = testCases[ i ].resExponent;

        if (veryVerbose) cout << endl
                              << "Test 'multiply(ValueType32,"
                              << " ValueType32)'," << endl
                              << "'multiply(ValueType64,"
                              << " ValueType64)'" << endl
                              << "and 'multiply(ValueType128,"
                              << " ValueType128)' on" << endl
                              << lhsMantissa << "e" << lhsExponent
                              << " * "
                              << rhsMantissa << "e" << rhsExponent
                              << " == "
                              << resMantissa << "e" << resExponent << endl;

        Util::ValueType32 identity32 = Util::parse32("1");

        lhs32 = Util::makeDecimalRaw32(static_cast<int>(lhsMantissa),
                                                        lhsExponent);
        rhs32 = Util::makeDecimalRaw32(static_cast<int>(rhsMantissa),
                                                        rhsExponent);
        result32 = Util::multiply(lhs32, rhs32);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(
                        result32,
                        Util::makeDecimalRaw32(static_cast<int>(resMantissa),
                                                                resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs32, Util::multiply(lhs32, identity32)));


        Util::ValueType64 identity64 = Util::parse64("1");

           lhs64 = Util::makeDecimalRaw64(lhsMantissa, lhsExponent);
           rhs64 = Util::makeDecimalRaw64(rhsMantissa, rhsExponent);
        result64 = Util::multiply(lhs64, rhs64);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result64, Util::makeDecimalRaw64(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs64, Util::multiply(lhs64, identity64)));


        Util::ValueType128 identity128 = Util::parse128("1");

           lhs128 = Util::makeDecimalRaw128(lhsMantissa, lhsExponent);
           rhs128 = Util::makeDecimalRaw128(rhsMantissa, rhsExponent);
        result128 = Util::multiply(lhs128, rhs128);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result128, Util::makeDecimalRaw128(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs128, Util::multiply(lhs128,
                                                  identity128)));
    }


                    // Testing for 'NaN'/'Inf' special cases:
    {
        //:             L * R|-Inf|Normal|+Inf|NaN|Zero|
        //:            ------+----+------+----+---+----+
        //:             -Inf |+Inf|+/-Inf|-Inf|NaN| NaN|
        //:            ------+----+------+----+---+----+
        //:            Normal| Inf|Normal| Inf|NaN|+/-0|
        //:            ------+----+------+----+---+----+
        //:             +Inf |-Inf|+/-Inf|+Inf|NaN| NaN|
        //:            ------+----+------+----+---+----+
        //:              NaN | NaN|  NaN | NaN|NaN| NaN|
        //:            ------+----+------+----+---+----+
        //:             Zero | NaN| +/-0 | NaN|NaN|+/-0|


        Util::ValueType32    max32 = Util::max32();
        Util::ValueType32    min32 = Util::min32();
        Util::ValueType32   zero32 = Util::parse32("+0.0");
        Util::ValueType32   ninf32 = Util::parse32("-Inf");
        Util::ValueType32   pinf32 = Util::parse32("+Inf");
        Util::ValueType32    nan32 = Util::parse32( "NaN");
        Util::ValueType32   snan32 = Util::parse32("sNaN");
        Util::ValueType32 normal32 = Util::makeDecimalRaw32(42,1);

        ASSERT(nanEqual(pinf32, Util::multiply(  ninf32,   ninf32)));
        ASSERT(nanEqual(ninf32, Util::multiply(  ninf32, normal32)));
        ASSERT(nanEqual(ninf32, Util::multiply(  ninf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::multiply(  ninf32,    nan32)));
        ASSERT(nanEqual( nan32, Util::multiply(  ninf32,   zero32)));

        ASSERT(nanEqual(ninf32, Util::multiply(normal32,   ninf32)));
        ASSERT(nanEqual(        Util::multiply(normal32, normal32),
                        Util::makeDecimalRaw32(42*42,2)));
        ASSERT(nanEqual(pinf32, Util::multiply(normal32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::multiply(normal32,    nan32)));
        ASSERT(nanEqual(zero32, Util::multiply(normal32,   zero32)));

        ASSERT(nanEqual(ninf32, Util::multiply(  pinf32,   ninf32)));
        ASSERT(nanEqual(pinf32, Util::multiply(  pinf32, normal32)));
        ASSERT(nanEqual(pinf32, Util::multiply(  pinf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::multiply(  pinf32,    nan32)));
        ASSERT(nanEqual( nan32, Util::multiply(  pinf32,   zero32)));

        ASSERT(nanEqual( nan32, Util::multiply(   nan32,   ninf32)));
        ASSERT(nanEqual( nan32, Util::multiply(   nan32, normal32)));
        ASSERT(nanEqual( nan32, Util::multiply(   nan32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::multiply(   nan32,    nan32)));
        ASSERT(nanEqual( nan32, Util::multiply(   nan32,   zero32)));

        ASSERT(nanEqual( nan32, Util::multiply(  zero32,   ninf32)));
        ASSERT(nanEqual(zero32, Util::multiply(  zero32, normal32)));
        ASSERT(nanEqual( nan32, Util::multiply(  zero32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::multiply(  zero32,    nan32)));
        ASSERT(nanEqual(zero32, Util::multiply(  zero32,   zero32)));

        ASSERT(nanEqual(pinf32, Util::multiply(   max32,    max32)));
        ASSERT(nanEqual(zero32, Util::multiply(   min32,    min32)));

        errno = 0;
        ASSERT(nanEqual( nan32, Util::multiply(  snan32,   snan32)));
        ASSERT(EDOM == errno);

        Util::ValueType64    max64 = Util::max64();
        Util::ValueType64    min64 = Util::min64();
        Util::ValueType64   zero64 = Util::parse64("+0.0");
        Util::ValueType64   ninf64 = Util::parse64("-Inf");
        Util::ValueType64   pinf64 = Util::parse64("+Inf");
        Util::ValueType64    nan64 = Util::parse64( "NaN");
        Util::ValueType64   snan64 = Util::parse64("sNaN");
        Util::ValueType64 normal64 = Util::makeDecimalRaw64(42,1);

        ASSERT(nanEqual(pinf64, Util::multiply(  ninf64,   ninf64)));
        ASSERT(nanEqual(ninf64, Util::multiply(  ninf64, normal64)));
        ASSERT(nanEqual(ninf64, Util::multiply(  ninf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::multiply(  ninf64,    nan64)));
        ASSERT(nanEqual( nan64, Util::multiply(  ninf64,   zero64)));

        ASSERT(nanEqual(ninf64, Util::multiply(normal64,   ninf64)));
        ASSERT(nanEqual(        Util::multiply(normal64, normal64),
                        Util::makeDecimalRaw64(42*42,2)));
        ASSERT(nanEqual(pinf64, Util::multiply(normal64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::multiply(normal64,    nan64)));
        ASSERT(nanEqual(zero64, Util::multiply(normal64,   zero64)));

        ASSERT(nanEqual(ninf64, Util::multiply(  pinf64,   ninf64)));
        ASSERT(nanEqual(pinf64, Util::multiply(  pinf64, normal64)));
        ASSERT(nanEqual(pinf64, Util::multiply(  pinf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::multiply(  pinf64,    nan64)));
        ASSERT(nanEqual( nan64, Util::multiply(  pinf64,   zero64)));

        ASSERT(nanEqual( nan64, Util::multiply(   nan64,   ninf64)));
        ASSERT(nanEqual( nan64, Util::multiply(   nan64, normal64)));
        ASSERT(nanEqual( nan64, Util::multiply(   nan64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::multiply(   nan64,    nan64)));
        ASSERT(nanEqual( nan64, Util::multiply(   nan64,   zero64)));

        ASSERT(nanEqual( nan64, Util::multiply(  zero64,   ninf64)));
        ASSERT(nanEqual(zero64, Util::multiply(  zero64, normal64)));
        ASSERT(nanEqual( nan64, Util::multiply(  zero64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::multiply(  zero64,    nan64)));
        ASSERT(nanEqual(zero64, Util::multiply(  zero64,   zero64)));

        ASSERT(nanEqual(pinf64, Util::multiply(   max64,    max64)));
        ASSERT(nanEqual(zero64, Util::multiply(   min64,    min64)));

        errno = 0;
        ASSERT(nanEqual( nan64, Util::multiply(  snan64,   snan64)));
        ASSERT(EDOM == errno);

        Util::ValueType128   max128  = Util::max128();
        Util::ValueType128   min128  = Util::min128();
        Util::ValueType128   zero128 = Util::parse128("+0.0");
        Util::ValueType128   ninf128 = Util::parse128("-Inf");
        Util::ValueType128   pinf128 = Util::parse128("+Inf");
        Util::ValueType128    nan128 = Util::parse128( "NaN");
        Util::ValueType128   snan128 = Util::parse128("sNaN");
        Util::ValueType128 normal128 = Util::makeDecimalRaw128(42,1);

        ASSERT(nanEqual(pinf128, Util::multiply(  ninf128,   ninf128)));
        ASSERT(nanEqual(ninf128, Util::multiply(  ninf128, normal128)));
        ASSERT(nanEqual(ninf128, Util::multiply(  ninf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::multiply(  ninf128,    nan128)));
        ASSERT(nanEqual( nan128, Util::multiply(  ninf128,   zero128)));

        ASSERT(nanEqual(ninf128, Util::multiply(normal128,   ninf128)));
        ASSERT(nanEqual(         Util::multiply(normal128, normal128),
                        Util::makeDecimalRaw128(42*42, 2)));
        ASSERT(nanEqual(pinf128, Util::multiply(normal128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::multiply(normal128,    nan128)));
        ASSERT(nanEqual(zero128, Util::multiply(normal128,   zero128)));

        ASSERT(nanEqual(ninf128, Util::multiply(  pinf128,   ninf128)));
        ASSERT(nanEqual(pinf128, Util::multiply(  pinf128, normal128)));
        ASSERT(nanEqual(pinf128, Util::multiply(  pinf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::multiply(  pinf128,    nan128)));
        ASSERT(nanEqual( nan128, Util::multiply(  pinf128,   zero128)));

        ASSERT(nanEqual( nan128, Util::multiply(   nan128,   ninf128)));
        ASSERT(nanEqual( nan128, Util::multiply(   nan128, normal128)));
        ASSERT(nanEqual( nan128, Util::multiply(   nan128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::multiply(   nan128,    nan128)));
        ASSERT(nanEqual( nan128, Util::multiply(   nan128,   zero128)));

        ASSERT(nanEqual( nan128, Util::multiply(  zero128,   ninf128)));
        ASSERT(nanEqual(zero128, Util::multiply(  zero128, normal128)));
        ASSERT(nanEqual( nan128, Util::multiply(  zero128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::multiply(  zero128,    nan128)));
        ASSERT(nanEqual(zero128, Util::multiply(  zero128,   zero128)));

        ASSERT(nanEqual(pinf128, Util::multiply(   max128,    max128)));
        ASSERT(nanEqual(zero128, Util::multiply(   min128,    min128)));

        errno = 0;
        ASSERT(nanEqual( nan128, Util::multiply(  snan128,   snan128)));
        ASSERT(EDOM == errno);
   }
}

void TestDriver::testCase6()
{
    // ------------------------------------------------------------------------
    // ARITHMETIC FUNCTION 'subtract'
    //
    // Concerns:
    //:  1 'subtract' should never (except in identity, 'NaN' and 'Inf' cases)
    //:    return the same value as at least one of the operands.
    //:
    //:  2 'subtract' behaves correctly with identity operands (0 and -0).
    //:
    //:  3 'subtract' will return a distinct value from both of its operands,
    //:    when both are non-zero and value-states (not 'NaN' or 'Inf').
    //:
    //:  4 'subtract' to 'NaN' or 'Inf' should follow the IEEE rules for the
    //:    cases listed in this chart:
    //:
    //:             L - R|-Inf|Normal|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:             -Inf | NaN| -Inf |-Inf|NaN|
    //:            ------+----+------+----+---+
    //:            Normal|+Inf|Normal|-Inf|NaN|
    //:            ------+----+------+----+---+
    //:             +Inf |+Inf| +Inf | NaN|NaN|
    //:            ------+----+------+----+---+
    //:              NaN | NaN|  NaN | NaN|NaN|
    //:
    //:  5 'subtract' behaves reasonably when working with different
    //:    quanta.
    //
    // Plan:
    //:  1 Test a handful of expected values of different exponent and
    //:    mantissa, with both possible orders. (C-1,5,6)
    //:
    //:  2 Test identity with both '-0' and '0' cases. (C-2)
    //:
    //:  3 When not dealing with special cases (or rounding cases), make sure
    //:    the result value does not compare equal to either source. (C-3)
    //:
    //:  4 Test all 16 special cases in the chart, which covers both orders.
    //:    (C-4,6)
    //
    // Testing:
    //   subtract(ValueType32,  ValueType32)
    //   subtract(ValueType64,  ValueType64)
    //   subtract(ValueType128, ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "ARITHMETIC FUNCTION 'subtract'" << endl
                      << "==============================" << endl;

    Util::ValueType32     lhs32;
    Util::ValueType32     rhs32;
    Util::ValueType32  result32;

    Util::ValueType64     lhs64;
    Util::ValueType64     rhs64;
    Util::ValueType64  result64;

    Util::ValueType128    lhs128;
    Util::ValueType128    rhs128;
    Util::ValueType128 result128;

    struct  {
        long long int lhsMantissa;
                  int lhsExponent;
        long long int rhsMantissa;
                  int rhsExponent;
        long long int resMantissa;
                  int resExponent;
    } testCases[] = {
        {  0,  0,  0,  0,  0,  0 },
        {  1,  0,  0,  0,  1,  0 },
        {  0,  0,  1,  0, -1,  0 },
        { 42,  0,  0,  0, 42,  0 },
        {  0,  0, 42,  0,-42,  0 },
        { 42,  0,  1,  0, 41,  0 },
        {  1,  0, 42,  0,-41,  0 },
        { 42,  0,  1,  1, 32,  0 },
        {  1,  1, 42,  0,-32,  0 }
    };
    const int numTestCases = static_cast<int>(sizeof(testCases) /
                                              sizeof(*testCases));

    for (int i = 0; i < numTestCases; ++i) {
        long long int lhsMantissa = testCases[ i ].lhsMantissa;
                  int lhsExponent = testCases[ i ].lhsExponent;
        long long int rhsMantissa = testCases[ i ].rhsMantissa;
                  int rhsExponent = testCases[ i ].rhsExponent;
        long long int resMantissa = testCases[ i ].resMantissa;
                  int resExponent = testCases[ i ].resExponent;

        if (veryVerbose) cout << endl
                              << "Test 'subtract(ValueType32,"
                              << " ValueType32)'," << endl
                              << "'subtract(ValueType64,"
                              << " ValueType64)'" << endl
                              << "and 'subtract(ValueType128,"
                              << " ValueType128)' on" << endl
                              << lhsMantissa << "e" << lhsExponent
                              << " - "
                              << rhsMantissa << "e" << rhsExponent
                              << " == "
                              << resMantissa << "e" << resExponent << endl;

        Util::ValueType32 negativeZero32 = Util::parse32("-0");

        lhs32 = Util::makeDecimalRaw32(static_cast<int>(lhsMantissa),
                                                        lhsExponent);
        rhs32 = Util::makeDecimalRaw32(static_cast<int>(rhsMantissa),
                                                        rhsExponent);
        result32 = Util::subtract(lhs32, rhs32);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(
                        result32,
                        Util::makeDecimalRaw32(static_cast<int>(resMantissa),
                                                                resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs32, Util::add(lhs32, negativeZero32)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs32, Util::add(negativeZero32, lhs32)));


        Util::ValueType64 negativeZero64 = Util::parse64("-0");

           lhs64 = Util::makeDecimalRaw64(lhsMantissa, lhsExponent);
           rhs64 = Util::makeDecimalRaw64(rhsMantissa, rhsExponent);
        result64 = Util::subtract(lhs64, rhs64);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(result64,
                                 Util::makeDecimalRaw64(resMantissa,
                                                        resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs64, Util::subtract(lhs64, negativeZero64)));


        Util::ValueType128 negativeZero128 = Util::parse128("-0");

           lhs128 = Util::makeDecimalRaw128(lhsMantissa, lhsExponent);
           rhs128 = Util::makeDecimalRaw128(rhsMantissa, rhsExponent);
        result128 = Util::subtract(lhs128, rhs128);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(result128,
                                 Util::makeDecimalRaw128(resMantissa,
                                                         resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(lhs128,
                                 Util::subtract(lhs128,
                                                negativeZero128)));
    }


                    // Testing for 'NaN'/'Inf' special cases:
    {
        //:             L - R|-Inf|Normal|+Inf|NaN|
        //:            ------+----+------+----+---+
        //:             -Inf | NaN| -Inf |-Inf|NaN|
        //:            ------+----+------+----+---+
        //:            Normal|+Inf|Normal|-Inf|NaN|
        //:            ------+----+------+----+---+
        //:             +Inf |+Inf| +Inf | NaN|NaN|
        //:            ------+----+------+----+---+
        //:              NaN | NaN|  NaN | NaN|NaN|

        Util::ValueType32   ninf32 = Util::parse32("-Inf");
        Util::ValueType32   pinf32 = Util::parse32("+Inf");
        Util::ValueType32    nan32 = Util::parse32( "NaN");
        Util::ValueType32   snan32 = Util::parse32("sNaN");
        Util::ValueType32 normal32 = Util::makeDecimalRaw32(42,1);

        ASSERT(nanEqual( nan32, Util::subtract(  ninf32,   ninf32)));
        ASSERT(nanEqual(ninf32, Util::subtract(  ninf32, normal32)));
        ASSERT(nanEqual(ninf32, Util::subtract(  ninf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::subtract(  ninf32,    nan32)));

        ASSERT(nanEqual(pinf32, Util::subtract(normal32,   ninf32)));
        ASSERT(nanEqual(        Util::subtract(normal32, normal32),
                        Util::makeDecimalRaw32( 0, 1)));
        ASSERT(nanEqual(ninf32, Util::subtract(normal32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::subtract(normal32,    nan32)));

        ASSERT(nanEqual(pinf32, Util::subtract(  pinf32,   ninf32)));
        ASSERT(nanEqual(pinf32, Util::subtract(  pinf32, normal32)));
        ASSERT(nanEqual( nan32, Util::subtract(  pinf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::subtract(  pinf32,    nan32)));

        ASSERT(nanEqual( nan32, Util::subtract(   nan32,   ninf32)));
        ASSERT(nanEqual( nan32, Util::subtract(   nan32, normal32)));
        ASSERT(nanEqual( nan32, Util::subtract(   nan32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::subtract(   nan32,    nan32)));

        errno = 0;
        ASSERT(nanEqual( nan32, Util::subtract(  snan32,   snan32)));
        ASSERT(EDOM == errno);

        Util::ValueType64   ninf64 = Util::parse64("-Inf");
        Util::ValueType64   pinf64 = Util::parse64("+Inf");
        Util::ValueType64    nan64 = Util::parse64( "NaN");
        Util::ValueType64   snan64 = Util::parse64("sNaN");
        Util::ValueType64 normal64 = Util::makeDecimalRaw64(42,1);

        ASSERT(nanEqual( nan64, Util::subtract(  ninf64,   ninf64)));
        ASSERT(nanEqual(ninf64, Util::subtract(  ninf64, normal64)));
        ASSERT(nanEqual(ninf64, Util::subtract(  ninf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::subtract(  ninf64,    nan64)));

        ASSERT(nanEqual(pinf64, Util::subtract(normal64,   ninf64)));
        ASSERT(nanEqual(        Util::subtract(normal64, normal64),
                        Util::makeDecimalRaw64( 0, 1)));
        ASSERT(nanEqual(ninf64, Util::subtract(normal64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::subtract(normal64,    nan64)));

        ASSERT(nanEqual(pinf64, Util::subtract(  pinf64,   ninf64)));
        ASSERT(nanEqual(pinf64, Util::subtract(  pinf64, normal64)));
        ASSERT(nanEqual( nan64, Util::subtract(  pinf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::subtract(  pinf64,    nan64)));

        ASSERT(nanEqual( nan64, Util::subtract(   nan64,   ninf64)));
        ASSERT(nanEqual( nan64, Util::subtract(   nan64, normal64)));
        ASSERT(nanEqual( nan64, Util::subtract(   nan64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::subtract(   nan64,    nan64)));

        errno = 0;
        ASSERT(nanEqual( nan64, Util::subtract(  snan64,   snan64)));
        ASSERT(EDOM == errno);

        Util::ValueType128   ninf128 = Util::parse128("-Inf");
        Util::ValueType128   pinf128 = Util::parse128("+Inf");
        Util::ValueType128    nan128 = Util::parse128( "NaN");
        Util::ValueType128   snan128 = Util::parse128("sNaN");
        Util::ValueType128 normal128 = Util::makeDecimalRaw128(42,1);

        ASSERT(nanEqual( nan128, Util::subtract(  ninf128,   ninf128)));
        ASSERT(nanEqual(ninf128, Util::subtract(  ninf128, normal128)));
        ASSERT(nanEqual(ninf128, Util::subtract(  ninf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::subtract(  ninf128,    nan128)));

        ASSERT(nanEqual(pinf128, Util::subtract(normal128,   ninf128)));
        ASSERT(nanEqual(         Util::subtract(normal128, normal128),
                        Util::makeDecimalRaw128( 0, 1)));
        ASSERT(nanEqual(ninf128, Util::subtract(normal128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::subtract(normal128,    nan128)));

        ASSERT(nanEqual(pinf128, Util::subtract(  pinf128,   ninf128)));
        ASSERT(nanEqual(pinf128, Util::subtract(  pinf128, normal128)));
        ASSERT(nanEqual( nan128, Util::subtract(  pinf128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::subtract(  pinf128,    nan128)));

        ASSERT(nanEqual( nan128, Util::subtract(   nan128,   ninf128)));
        ASSERT(nanEqual( nan128, Util::subtract(   nan128, normal128)));
        ASSERT(nanEqual( nan128, Util::subtract(   nan128,   pinf128)));
        ASSERT(nanEqual( nan128, Util::subtract(   nan128,    nan128)));

        errno = 0;
        ASSERT(nanEqual( nan128, Util::subtract(  snan128,   snan128)));
        ASSERT(EDOM == errno);
    }
}

void TestDriver::testCase5()
{
    // ------------------------------------------------------------------------
    // ARITHMETIC FUNCTION 'add'
    //
    // Concerns:
    //:  1 'add' should never (except in 'NaN' and 'Inf' cases) return the same
    //:    value as at least one of the operands.
    //:
    //:  2 'add' behaves correctly with identity operands (0 and -0).
    //:
    //:  3 'add' will return a distinct value from both of its operands, when
    //:    both are non-zero and value-states (not 'NaN' or 'Inf').
    //:
    //:  4 'add' to 'NaN' or 'Inf' should follow the IEEE rules for the cases
    //:    listed in this chart:
    //:
    //:             L + R|-Inf|Normal|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:             -Inf |-Inf| -Inf | NaN|NaN|
    //:            ------+----+------+----+---+
    //:            Normal|-Inf|Normal|+Inf|NaN|
    //:            ------+----+------+----+---+
    //:             +Inf | NaN| +Inf |+Inf|NaN|
    //:            ------+----+------+----+---+
    //:              NaN | NaN|  NaN | NaN|NaN|
    //:
    //:  5 'add' behaves reasonably when working with different quanta.
    //:
    //:  6 'add' must be a commutative operation (when avoiding corner cases).
    //
    // Plan:
    //:  1 Test a handful of expected values of different exponent and
    //:    mantissa, with both possible orders. (C-1,5,6)
    //:
    //:  2 Test identity with both '-0' and '0' cases. (C-2)
    //:
    //:  3 When not dealing with special cases (or rounding cases), make sure
    //:    the result value does not compare equal to either source.  (C-3)
    //:
    //:  4 Test all 16 special cases in the chart, which covers both orders.
    //:    (C-4,6)
    //
    // Testing:
    //   add(ValueType32,  ValueType32)
    //   add(ValueType64,  ValueType64)
    //   add(ValueType128, ValueType128)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "ARITHMETIC FUNCTION 'add'" << endl
                      << "=========================" << endl;

    Util::ValueType32     lhs32;
    Util::ValueType32     rhs32;
    Util::ValueType32  result32;

    Util::ValueType64     lhs64;
    Util::ValueType64     rhs64;
    Util::ValueType64  result64;

    Util::ValueType128    lhs128;
    Util::ValueType128    rhs128;
    Util::ValueType128 result128;

    struct {
        long long int lhsMantissa;
                  int lhsExponent;
        long long int rhsMantissa;
                  int rhsExponent;
        long long int resMantissa;
                  int resExponent;
    } testCases[] = {
        {  0,  0,  0,  0,  0,  0 },
        {  1,  0,  0,  0,  1,  0 },
        {  0,  0,  1,  0,  1,  0 },
        { 42,  0,  0,  0, 42,  0 },
        {  0,  0, 42,  0, 42,  0 },
        { 42,  0,  1,  0, 43,  0 },
        {  1,  0, 42,  0, 43,  0 },
        { 42,  0,  1,  1, 52,  0 },
        {  1,  1, 42,  0, 52,  0 }
    };
    const int numTestCases = static_cast<int>(sizeof(testCases) /
                                              sizeof(*testCases));

    for (int i = 0; i < numTestCases; ++i) {
        long long int lhsMantissa = testCases[ i ].lhsMantissa;
                  int lhsExponent = testCases[ i ].lhsExponent;
        long long int rhsMantissa = testCases[ i ].rhsMantissa;
                  int rhsExponent = testCases[ i ].rhsExponent;
        long long int resMantissa = testCases[ i ].resMantissa;
                  int resExponent = testCases[ i ].resExponent;

        if (veryVerbose) cout << endl
                              << "Test 'add(ValueType32,"
                              << " ValueType32)'," << endl
                              << "'add(ValueType64,"
                              << " ValueType64)'" << endl
                              << "and 'add(ValueType128,"
                              << " ValueType128)' on" << endl
                              << lhsMantissa << "e" << lhsExponent
                              << " + "
                              << rhsMantissa << "e" << rhsExponent
                              << " == "
                              << resMantissa << "e" << resExponent << endl;

        Util::ValueType32 negativeZero32 = Util::parse32("-0");

        lhs32 = Util::makeDecimalRaw32(static_cast<int>(lhsMantissa),
                                                        lhsExponent);
        rhs32 = Util::makeDecimalRaw32(static_cast<int>(rhsMantissa),
                                                        rhsExponent);
        result32 = Util::add(lhs32, rhs32);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
                     Util::equal(result32,
                        Util::makeDecimalRaw32(static_cast<int>(resMantissa),
                                                                resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs32, Util::subtract(lhs32, negativeZero32)));


        Util::ValueType64 negativeZero64 = Util::parse64("-0");

           lhs64 = Util::makeDecimalRaw64(lhsMantissa, lhsExponent);
           rhs64 = Util::makeDecimalRaw64(rhsMantissa, rhsExponent);
           result64 = Util::add(lhs64, rhs64);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result64, Util::makeDecimalRaw64(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs64, Util::add(lhs64, negativeZero64)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs64, Util::add(negativeZero64, lhs64)));


        Util::ValueType128 negativeZero128 = Util::parse128("-0");

           lhs128 = Util::makeDecimalRaw128(lhsMantissa, lhsExponent);
           rhs128 = Util::makeDecimalRaw128(rhsMantissa, rhsExponent);
        result128 = Util::add(lhs128, rhs128);

        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(result128, Util::makeDecimalRaw128(resMantissa,
                                                            resExponent)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs128, Util::add(lhs128, negativeZero128)));
        LOOP6_ASSERT(lhsMantissa, lhsExponent,
                     rhsMantissa, rhsExponent,
                     resMantissa, resExponent,
               Util::equal(lhs128, Util::add(negativeZero128, lhs128)));
    }

                    // Testing for 'NaN'/'Inf' special cases:

    {
        //:             L + R|-Inf|Normal|+Inf|NaN|
        //:            ------+----+------+----+---+
        //:             -Inf |-Inf| -Inf | NaN|NaN|
        //:            ------+----+------+----+---+
        //:            Normal|-Inf|Normal|+Inf|NaN|
        //:            ------+----+------+----+---+
        //:             +Inf | NaN| +Inf |+Inf|NaN|
        //:            ------+----+------+----+---+
        //:              NaN | NaN|  NaN | NaN|NaN|

        Util::ValueType32   ninf32 = Util::parse32("-Inf");
        Util::ValueType32   pinf32 = Util::parse32("+Inf");
        Util::ValueType32    nan32 = Util::parse32( "NaN");
        Util::ValueType32   snan32 = Util::parse32("sNaN");
        ASSERT( Util::equal(pinf32, pinf32));
        ASSERT( Util::equal(ninf32, ninf32));
        ASSERT( Util::notEqual(pinf32, ninf32));
        ASSERT(!Util::equal(nan32, nan32));
        ASSERT( Util::notEqual(nan32, nan32));
        Util::ValueType32 normal32 = Util::makeDecimalRaw32(42,1);

        ASSERT(nanEqual(ninf32, Util::add(  ninf32,   ninf32)));
        ASSERT(nanEqual(ninf32, Util::add(  ninf32, normal32)));
        ASSERT(nanEqual( nan32, Util::add(  ninf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::add(  ninf32,    nan32)));

        ASSERT(nanEqual(ninf32, Util::add(normal32,   ninf32)));
        ASSERT(nanEqual(        Util::add(normal32, normal32),
                        Util::makeDecimalRaw32(84,1)));
        ASSERT(nanEqual(pinf32, Util::add(normal32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::add(normal32,    nan32)));

        ASSERT(nanEqual( nan32, Util::add(  pinf32,   ninf32)));
        ASSERT(nanEqual(pinf32, Util::add(  pinf32, normal32)));
        ASSERT(nanEqual(pinf32, Util::add(  pinf32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::add(  pinf32,    nan32)));

        ASSERT(nanEqual( nan32, Util::add(   nan32,   ninf32)));
        ASSERT(nanEqual( nan32, Util::add(   nan32, normal32)));
        ASSERT(nanEqual( nan32, Util::add(   nan32,   pinf32)));
        ASSERT(nanEqual( nan32, Util::add(   nan32,    nan32)));

        errno = 0;
        ASSERT(nanEqual( nan32, Util::add(  snan32,   snan32)));
        ASSERT(EDOM == errno);

        Util::ValueType64   ninf64 = Util::parse64("-Inf");
        Util::ValueType64   pinf64 = Util::parse64("+Inf");
        Util::ValueType64    nan64 = Util::parse64( "NaN");
        Util::ValueType64   snan64 = Util::parse64("sNaN");
        ASSERT( Util::equal(pinf64, pinf64));
        ASSERT( Util::equal(ninf64, ninf64));
        ASSERT( Util::notEqual(pinf64, ninf64));
        ASSERT(!Util::equal(nan64, nan64));
        ASSERT( Util::notEqual(nan64, nan64));
        Util::ValueType64 normal64 = Util::makeDecimalRaw64(42,1);

        ASSERT(nanEqual(ninf64, Util::add(  ninf64,   ninf64)));
        ASSERT(nanEqual(ninf64, Util::add(  ninf64, normal64)));
        ASSERT(nanEqual( nan64, Util::add(  ninf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::add(  ninf64,    nan64)));

        ASSERT(nanEqual(ninf64, Util::add(normal64,   ninf64)));
        ASSERT(nanEqual(        Util::add(normal64, normal64),
                        Util::makeDecimalRaw64(84,1)));
        ASSERT(nanEqual(pinf64, Util::add(normal64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::add(normal64,    nan64)));

        ASSERT(nanEqual( nan64, Util::add(  pinf64,   ninf64)));
        ASSERT(nanEqual(pinf64, Util::add(  pinf64, normal64)));
        ASSERT(nanEqual(pinf64, Util::add(  pinf64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::add(  pinf64,    nan64)));

        ASSERT(nanEqual( nan64, Util::add(   nan64,   ninf64)));
        ASSERT(nanEqual( nan64, Util::add(   nan64, normal64)));
        ASSERT(nanEqual( nan64, Util::add(   nan64,   pinf64)));
        ASSERT(nanEqual( nan64, Util::add(   nan64,    nan64)));

        errno = 0;
        ASSERT(nanEqual( nan64, Util::add(  snan64,   snan64)));
        ASSERT(EDOM == errno);

        Util::ValueType128   ninf128 = Util::parse128("-Inf");
        Util::ValueType128   pinf128 = Util::parse128("+Inf");
        Util::ValueType128    nan128 = Util::parse128( "NaN");
        Util::ValueType128   snan128 = Util::parse128("sNaN");
        Util::ValueType128 normal128 = Util::makeDecimalRaw128(42,1);

        ASSERT(nanEqual(  ninf128, Util::add(  ninf128,   ninf128)));
        ASSERT(nanEqual(  ninf128, Util::add(  ninf128, normal128)));
        ASSERT(nanEqual(   nan128, Util::add(  ninf128,   pinf128)));
        ASSERT(nanEqual(   nan128, Util::add(  ninf128,    nan128)));

        ASSERT(nanEqual(  ninf128, Util::add(normal128,   ninf128)));
        ASSERT(nanEqual(           Util::add(normal128, normal128),
                        Util::makeDecimalRaw128(84,1)));
        ASSERT(nanEqual(  pinf128, Util::add(normal128,   pinf128)));
        ASSERT(nanEqual(   nan128, Util::add(normal128,    nan128)));

        ASSERT(nanEqual(   nan128, Util::add(  pinf128,   ninf128)));
        ASSERT(nanEqual(  pinf128, Util::add(  pinf128, normal128)));
        ASSERT(nanEqual(  pinf128, Util::add(  pinf128,   pinf128)));
        ASSERT(nanEqual(   nan128, Util::add(  pinf128,    nan128)));

        ASSERT(nanEqual(   nan128, Util::add(   nan128,   ninf128)));
        ASSERT(nanEqual(   nan128, Util::add(   nan128, normal128)));
        ASSERT(nanEqual(   nan128, Util::add(   nan128,   pinf128)));
        ASSERT(nanEqual(   nan128, Util::add(   nan128,    nan128)));

        errno = 0;
        ASSERT(nanEqual( nan128, Util::add(  snan128,   snan128)));
        ASSERT(EDOM == errno);
    }
}

void TestDriver::testCase4()
{
    // ------------------------------------------------------------------------
    // INEQUALITY COMPARISON 'Util::notEqual'
    //
    // Concerns:
    //:  1 'notEqual' should return false if the bit patterns are the same (and
    //:    are not a bit pattern representing a 'NaN').
    //:
    //:  2 'notEqual' should return false if the bit patterns are different,
    //:    but represent the same value.  I.e. '10e0' should be equal to '1e1'.
    //:
    //:  3 Values which differ by only one of sign, exponent, or mantissa
    //:    should not be equal.
    //:
    //:  4 'NaN' values should never be equal.
    //:
    //:  5 The implementation of 'notEqual' normally would be a forwarding
    //:    function (to the underlying implementation), but some
    //:    implementations require a call to a helper function to determine
    //:    value.  This means that we don't have to aggressively test this
    //:    function, but should perform more than a cursory forwarding test.
    //:    (This will result in more than a simple forwarding test.)
    //:
    //:  6 Equality is a "Commutative" operation.
    //:       'A == B' implies 'B == A'
    //:    (Commutative property.)
    //:
    //:  7 Equality is a "Commutative" operation in the negative.
    //:       'A != B' implies 'B != A'
    //:    (Commutative property.)
    //:
    //:  8 Any two things equal to a third are equal to each other:
    //:       'A == B' and 'B == C' implies 'A == C'.
    //:    (Transitive property.)
    //:
    //:  9 Any two things equal to each other are both inequal to an inequal
    //:    third.
    //:       'A == B' and 'B != C' implies 'A != C'
    //:    (Transitive property.)
    //:
    //: 10 'NaN' and 'Inf' states are excluded from these rules and instead
    //:    have the following properties:
    //:
    //:     1  'NaN' !=  'NaN'
    //:     2  value !=  'NaN'
    //:     3  'NaN' !=  value
    //:     4 +'Inf' == +'Inf'
    //:     5 -'Inf' == -'Inf'
    //:     6 +'Inf' != -'Inf'
    //:     7 -'Inf' != +'Inf'
    //:     8  value != +'Inf'
    //:     9  value != -'Inf'
    //:    10 +'Inf' !=  value
    //:    11 -'Inf' !=  value
    //:    12  'NaN' != +'Inf'
    //:    13  'NaN' != -'Inf'
    //:    14 +'Inf' !=  'NaN'
    //:    15 -'Inf' !=  'NaN'
    //:
    //: 11 Inequality tests more than identity (same 'this' pointer).
    //:
    //: 12 'notEqual' should return false when there are two NaN arguments.
    //
    // Plan:
    //:  1 Myriad values will be tested for equality and inequality with
    //:    slightly altered values.  ('A != A + 1', and 'A + 1 != A', for
    //:    example)
    //:
    //:  2 All equality, and inequality tests will be tested with both
    //:    possible orderings to check the Commutative property.
    //:
    //:  3 Values will be tested for equality with copies of themselves
    //:
    //:  4 Create 'NaN' values, and compare them as inequal.
    //
    // Testing:
    //   notEqual(ValueType32,  ValueType32)
    //   notEqual(ValueType64,  ValueType64)
    //   notEqual(ValueType128, ValueType128)
    //   TEST 'notEqual' FOR 'NaN' CORRECTNESS
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "INEQUALITY COMPARISON 'Util::notEqual'" << endl
                      << "======================================" << endl;

    // Basic value comparison testing

    {

        Util::ValueType32  test32;
        Util::ValueType64  test64;
        Util::ValueType128 test128;

        Util::ValueType32  same32;
        Util::ValueType64  same64;
        Util::ValueType128 same128;

        Util::ValueType32  negated32;
        Util::ValueType64  negated64;
        Util::ValueType128 negated128;

        Util::ValueType32  incremented32;
        Util::ValueType64  incremented64;
        Util::ValueType128 incremented128;

        Util::ValueType32  exponentChanged32;
        Util::ValueType64  exponentChanged64;
        Util::ValueType128 exponentChanged128;

                //    0e0

                // (All 0's are special cases which only differ by mantissa
                // value not by exponent or sign.)

        test32 = Util::makeDecimalRaw32(0, 0);
        same32 = Util::makeDecimalRaw32(0, 0);
        incremented32 = Util::makeDecimalRaw32(1, 0);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, 0);
        same64 = Util::makeDecimalRaw64(0, 0);
        incremented64 = Util::makeDecimalRaw64(1, 0);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, 0);
        same128 = Util::makeDecimalRaw128(0, 0);
        incremented128 = Util::makeDecimalRaw128(1, 0);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));

                //    7e0

        test32 = Util::makeDecimalRaw32(7, 0);
        same32 = Util::makeDecimalRaw32(7, 0);
        negated32 = Util::makeDecimalRaw32(-7, 0);
        incremented32 = Util::makeDecimalRaw32(8, 0);
        exponentChanged32 = Util::makeDecimalRaw32(7, 2);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, 0);
        same64 = Util::makeDecimalRaw64(7, 0);
        negated64 = Util::makeDecimalRaw64(-7, 0);
        incremented64 = Util::makeDecimalRaw64(8, 0);
        exponentChanged64 = Util::makeDecimalRaw64(7, 2);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, 0);
        same128 = Util::makeDecimalRaw128(7, 0);
        negated128 = Util::makeDecimalRaw128(-7, 0);
        incremented128 = Util::makeDecimalRaw128(8, 0);
        exponentChanged128 = Util::makeDecimalRaw128(7, 2);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //  100e0

        test32 = Util::makeDecimalRaw32(100, 0);
        same32 = Util::makeDecimalRaw32(100, 0);
        negated32 = Util::makeDecimalRaw32(-100, 0);
        incremented32 = Util::makeDecimalRaw32(101, 0);
        exponentChanged32 = Util::makeDecimalRaw32(100, 2);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, 0);
        same64 = Util::makeDecimalRaw64(100, 0);
        negated64 = Util::makeDecimalRaw64(-100, 0);
        incremented64 = Util::makeDecimalRaw64(101, 0);
        exponentChanged64 = Util::makeDecimalRaw64(100, 2);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, 0);
        same128 = Util::makeDecimalRaw128(100, 0);
        negated128 = Util::makeDecimalRaw128(-100, 0);
        incremented128 = Util::makeDecimalRaw128(101, 0);
        exponentChanged128 = Util::makeDecimalRaw128(100, 2);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //   -7e0

        test32 = Util::makeDecimalRaw32(-7, 0);
        same32 = Util::makeDecimalRaw32(-7, 0);
        negated32 = Util::makeDecimalRaw32(7, 0);
        incremented32 = Util::makeDecimalRaw32(-6, 0);
        exponentChanged32 = Util::makeDecimalRaw32(-7, 2);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, 0);
        same64 = Util::makeDecimalRaw64(-7, 0);
        negated64 = Util::makeDecimalRaw64(7, 0);
        incremented64 = Util::makeDecimalRaw64(-6, 0);
        exponentChanged64 = Util::makeDecimalRaw64(-7, 2);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, 0);
        same128 = Util::makeDecimalRaw128(-7, 0);
        negated128 = Util::makeDecimalRaw128(7, 0);
        incremented128 = Util::makeDecimalRaw128(-6, 0);
        exponentChanged128 = Util::makeDecimalRaw128(-7, 2);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                // -100e0

        test32 = Util::makeDecimalRaw32(-100, 0);
        same32 = Util::makeDecimalRaw32(-100, 0);
        negated32 = Util::makeDecimalRaw32(100, 0);
        incremented32 = Util::makeDecimalRaw32(-99, 0);
        exponentChanged32 = Util::makeDecimalRaw32(-100, 2);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, 0);
        same64 = Util::makeDecimalRaw64(-100, 0);
        negated64 = Util::makeDecimalRaw64(100, 0);
        incremented64 = Util::makeDecimalRaw64(-99, 0);
        exponentChanged64 = Util::makeDecimalRaw64(-100, 2);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, 0);
        same128 = Util::makeDecimalRaw128(-100, 0);
        negated128 = Util::makeDecimalRaw128(100, 0);
        incremented128 = Util::makeDecimalRaw128(-99, 0);
        exponentChanged128 = Util::makeDecimalRaw128(-100, 2);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //    0e3

        test32 = Util::makeDecimalRaw32(0, 3);
        same32 = Util::makeDecimalRaw32(0, 3);
        incremented32 = Util::makeDecimalRaw32(1, 3);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, 3);
        same64 = Util::makeDecimalRaw64(0, 3);
        incremented64 = Util::makeDecimalRaw64(1, 3);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, 3);
        same128 = Util::makeDecimalRaw128(0, 3);
        incremented128 = Util::makeDecimalRaw128(1, 3);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));

                //    7e3

        test32 = Util::makeDecimalRaw32(7, 3);
        same32 = Util::makeDecimalRaw32(7, 3);
        negated32 = Util::makeDecimalRaw32(-7, 3);
        incremented32 = Util::makeDecimalRaw32(8, 3);
        exponentChanged32 = Util::makeDecimalRaw32(7, 5);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, 3);
        same64 = Util::makeDecimalRaw64(7, 3);
        negated64 = Util::makeDecimalRaw64(-7, 3);
        incremented64 = Util::makeDecimalRaw64(8, 3);
        exponentChanged64 = Util::makeDecimalRaw64(7, 5);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, 3);
        same128 = Util::makeDecimalRaw128(7, 3);
        negated128 = Util::makeDecimalRaw128(-7, 3);
        incremented128 = Util::makeDecimalRaw128(8, 3);
        exponentChanged128 = Util::makeDecimalRaw128(7, 5);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //  100e3

        test32 = Util::makeDecimalRaw32(100, 3);
        same32 = Util::makeDecimalRaw32(100, 3);
        negated32 = Util::makeDecimalRaw32(-100, 3);
        incremented32 = Util::makeDecimalRaw32(101, 3);
        exponentChanged32 = Util::makeDecimalRaw32(100, 5);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, 3);
        same64 = Util::makeDecimalRaw64(100, 3);
        negated64 = Util::makeDecimalRaw64(-100, 3);
        incremented64 = Util::makeDecimalRaw64(101, 3);
        exponentChanged64 = Util::makeDecimalRaw64(100, 5);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, 3);
        same128 = Util::makeDecimalRaw128(100, 3);
        negated128 = Util::makeDecimalRaw128(-100, 3);
        incremented128 = Util::makeDecimalRaw128(101, 3);
        exponentChanged128 = Util::makeDecimalRaw128(100, 5);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //   -7e3

        test32 = Util::makeDecimalRaw32(-7, 3);
        same32 = Util::makeDecimalRaw32(-7, 3);
        negated32 = Util::makeDecimalRaw32(7, 3);
        incremented32 = Util::makeDecimalRaw32(-6, 3);
        exponentChanged32 = Util::makeDecimalRaw32(-7, 5);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, 3);
        same64 = Util::makeDecimalRaw64(-7, 3);
        negated64 = Util::makeDecimalRaw64(7, 3);
        incremented64 = Util::makeDecimalRaw64(-6, 3);
        exponentChanged64 = Util::makeDecimalRaw64(-7, 5);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, 3);
        same128 = Util::makeDecimalRaw128(-7, 3);
        negated128 = Util::makeDecimalRaw128(7, 3);
        incremented128 = Util::makeDecimalRaw128(-6, 3);
        exponentChanged128 = Util::makeDecimalRaw128(-7, 5);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                // -100e3

        test32 = Util::makeDecimalRaw32(-100, 3);
        same32 = Util::makeDecimalRaw32(-100, 3);
        negated32 = Util::makeDecimalRaw32(100, 3);
        incremented32 = Util::makeDecimalRaw32(-99, 3);
        exponentChanged32 = Util::makeDecimalRaw32(-100, 5);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, 3);
        same64 = Util::makeDecimalRaw64(-100, 3);
        negated64 = Util::makeDecimalRaw64(100, 3);
        incremented64 = Util::makeDecimalRaw64(-99, 3);
        exponentChanged64 = Util::makeDecimalRaw64(-100, 5);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, 3);
        same128 = Util::makeDecimalRaw128(-100, 3);
        negated128 = Util::makeDecimalRaw128(100, 3);
        incremented128 = Util::makeDecimalRaw128(-99, 3);
        exponentChanged128 = Util::makeDecimalRaw128(-100, 5);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //    0e-5

        test32 = Util::makeDecimalRaw32(0, -5);
        same32 = Util::makeDecimalRaw32(0, -5);
        incremented32 = Util::makeDecimalRaw32(1, -5);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, -5);
        same64 = Util::makeDecimalRaw64(0, -5);
        incremented64 = Util::makeDecimalRaw64(1, -5);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, -5);
        same128 = Util::makeDecimalRaw128(0, -5);
        incremented128 = Util::makeDecimalRaw128(1, -5);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));

                //    7e-5

        test32 = Util::makeDecimalRaw32(7, -5);
        same32 = Util::makeDecimalRaw32(7, -5);
        negated32 = Util::makeDecimalRaw32(-7, -5);
        incremented32 = Util::makeDecimalRaw32(8, -5);
        exponentChanged32 = Util::makeDecimalRaw32(7, -3);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, -5);
        same64 = Util::makeDecimalRaw64(7, -5);
        negated64 = Util::makeDecimalRaw64(-7, -5);
        incremented64 = Util::makeDecimalRaw64(8, -5);
        exponentChanged64 = Util::makeDecimalRaw64(7, -3);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, -5);
        same128 = Util::makeDecimalRaw128(7, -5);
        negated128 = Util::makeDecimalRaw128(-7, -5);
        incremented128 = Util::makeDecimalRaw128(8, -5);
        exponentChanged128 = Util::makeDecimalRaw128(7, -3);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //  100e-5

        test32 = Util::makeDecimalRaw32(100, -5);
        same32 = Util::makeDecimalRaw32(100, -5);
        negated32 = Util::makeDecimalRaw32(-100, -5);
        incremented32 = Util::makeDecimalRaw32(101, -5);
        exponentChanged32 = Util::makeDecimalRaw32(100, -3);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, -5);
        same64 = Util::makeDecimalRaw64(100, -5);
        negated64 = Util::makeDecimalRaw64(-100, -5);
        incremented64 = Util::makeDecimalRaw64(101, -5);
        exponentChanged64 = Util::makeDecimalRaw64(100, -3);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, -5);
        same128 = Util::makeDecimalRaw128(100, -5);
        negated128 = Util::makeDecimalRaw128(-100, -5);
        incremented128 = Util::makeDecimalRaw128(101, -5);
        exponentChanged128 = Util::makeDecimalRaw128(100, -3);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                //   -7e-5

        test32 = Util::makeDecimalRaw32(-7, -5);
        same32 = Util::makeDecimalRaw32(-7, -5);
        negated32 = Util::makeDecimalRaw32(7, -5);
        incremented32 = Util::makeDecimalRaw32(-6, -5);
        exponentChanged32 = Util::makeDecimalRaw32(-7, -3);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, -5);
        same64 = Util::makeDecimalRaw64(-7, -5);
        negated64 = Util::makeDecimalRaw64(7, -5);
        incremented64 = Util::makeDecimalRaw64(-6, -5);
        exponentChanged64 = Util::makeDecimalRaw64(-7, -3);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, -5);
        same128 = Util::makeDecimalRaw128(-7, -5);
        negated128 = Util::makeDecimalRaw128(7, -5);
        incremented128 = Util::makeDecimalRaw128(-6, -5);
        exponentChanged128 = Util::makeDecimalRaw128(-7, -3);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

                // -100e-5

        test32 = Util::makeDecimalRaw32(-100, -5);
        same32 = Util::makeDecimalRaw32(-100, -5);
        negated32 = Util::makeDecimalRaw32(100, -5);
        incremented32 = Util::makeDecimalRaw32(-99, -5);
        exponentChanged32 = Util::makeDecimalRaw32(-100, -3);
        ASSERT(!Util::notEqual(test32, test32));
        ASSERT(!Util::notEqual(same32, test32));
        ASSERT(!Util::notEqual(test32, same32));
        ASSERT( Util::notEqual(negated32, test32));
        ASSERT( Util::notEqual(test32, negated32));
        ASSERT( Util::notEqual(incremented32, test32));
        ASSERT( Util::notEqual(test32, incremented32));
        ASSERT( Util::notEqual(exponentChanged32, test32));
        ASSERT( Util::notEqual(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, -5);
        same64 = Util::makeDecimalRaw64(-100, -5);
        negated64 = Util::makeDecimalRaw64(100, -5);
        incremented64 = Util::makeDecimalRaw64(-99, -5);
        exponentChanged64 = Util::makeDecimalRaw64(-100, -3);
        ASSERT(!Util::notEqual(test64, test64));
        ASSERT(!Util::notEqual(same64, test64));
        ASSERT(!Util::notEqual(test64, same64));
        ASSERT( Util::notEqual(negated64, test64));
        ASSERT( Util::notEqual(test64, negated64));
        ASSERT( Util::notEqual(incremented64, test64));
        ASSERT( Util::notEqual(test64, incremented64));
        ASSERT( Util::notEqual(exponentChanged64, test64));
        ASSERT( Util::notEqual(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, -5);
        same128 = Util::makeDecimalRaw128(-100, -5);
        negated128 = Util::makeDecimalRaw128(100, -5);
        incremented128 = Util::makeDecimalRaw128(-99, -5);
        exponentChanged128 = Util::makeDecimalRaw128(-100, -3);
        ASSERT(!Util::notEqual(test128, test128));
        ASSERT(!Util::notEqual(same128, test128));
        ASSERT(!Util::notEqual(test128, same128));
        ASSERT( Util::notEqual(negated128, test128));
        ASSERT( Util::notEqual(test128, negated128));
        ASSERT( Util::notEqual(incremented128, test128));
        ASSERT( Util::notEqual(test128, incremented128));
        ASSERT( Util::notEqual(exponentChanged128, test128));
        ASSERT( Util::notEqual(test128, exponentChanged128));

    }

    // Non bitwise notEqual testing:

    {
        Util::ValueType32 test32;
        Util::ValueType32 alt32;

        Util::ValueType64 test64;
        Util::ValueType64 alt64;

        Util::ValueType128 test128;
        Util::ValueType128 alt128;

                    // 0

        test32 = Util::makeDecimalRaw32(0, 0);
        alt32  = Util::makeDecimalRaw32(0, 5);

        ASSERT(!Util::notEqual(test32,  alt32));
        ASSERT(!Util::notEqual( alt32, test32));

        test64 = Util::makeDecimalRaw64(0, 0);
        alt64  = Util::makeDecimalRaw64(0, 5);

        ASSERT(!Util::notEqual(test64,  alt64));
        ASSERT(!Util::notEqual( alt64, test64));

        test128 = Util::makeDecimalRaw128(0, 0);
        alt128  = Util::makeDecimalRaw128(0, 5);

        ASSERT(!Util::notEqual(test128,  alt128));
        ASSERT(!Util::notEqual( alt128, test128));

                    // 700 vs 7e2

        test32 = Util::makeDecimalRaw32(700, 0);
        alt32  = Util::makeDecimalRaw32(7,   2);

        ASSERT(!Util::notEqual(test32,  alt32));
        ASSERT(!Util::notEqual( alt32, test32));

        test64 = Util::makeDecimalRaw64(700, 0);
        alt64  = Util::makeDecimalRaw64(7,   2);

        ASSERT(!Util::notEqual(test64,  alt64));
        ASSERT(!Util::notEqual( alt64, test64));

        test128 = Util::makeDecimalRaw128(700, 0);
        alt128  = Util::makeDecimalRaw128(7,   2);

        ASSERT(!Util::notEqual(test128,  alt128));
        ASSERT(!Util::notEqual( alt128, test128));
    }

    // Original testing for 'NaN problems.

    {
        Util::ValueType32  nan32  = Util::parse32( "NaN");
        Util::ValueType64  nan64  = Util::parse64( "NaN");
        Util::ValueType128 nan128 = Util::parse128("NaN");

        ASSERT(Util::notEqual(nan32,  nan32));
        ASSERT(Util::notEqual(nan64,  nan64));
        ASSERT(Util::notEqual(nan128, nan128));
    }

    {
        Util::ValueType32  nan32  = Util::parse32( "qNaN");
        Util::ValueType64  nan64  = Util::parse64( "qNaN");
        Util::ValueType128 nan128 = Util::parse128("qNaN");

        ASSERT(Util::notEqual(nan32,  nan32));
        ASSERT(Util::notEqual(nan64,  nan64));
        ASSERT(Util::notEqual(nan128, nan128));
    }

    {
        Util::ValueType32  nan32  = Util::parse32( "sNaN");
        Util::ValueType64  nan64  = Util::parse64( "sNaN");
        Util::ValueType128 nan128 = Util::parse128("sNaN");

        ASSERT(Util::notEqual(nan32,  nan32));
        ASSERT(Util::notEqual(nan64,  nan64));
        ASSERT(Util::notEqual(nan128, nan128));
    }

    // Transitivity tests

    {
        // Positive transitivity

        Util::ValueType32 a32;
        Util::ValueType32 b32;
        Util::ValueType32 c32;

        Util::ValueType64 a64;
        Util::ValueType64 b64;
        Util::ValueType64 c64;

        Util::ValueType128 a128;
        Util::ValueType128 b128;
        Util::ValueType128 c128;

        a32 = Util::makeDecimalRaw32(   1, 3);
        b32 = Util::makeDecimalRaw32(1000, 0);
        c32 = Util::makeDecimalRaw32(  10, 2);

        ASSERT(!Util::notEqual(a32, b32));
        ASSERT(!Util::notEqual(b32, a32));
        ASSERT(!Util::notEqual(b32, c32));
        ASSERT(!Util::notEqual(c32, b32));
        ASSERT(!Util::notEqual(a32, c32));
        ASSERT(!Util::notEqual(c32, a32));

        a64 = Util::makeDecimalRaw64(   1, 3);
        b64 = Util::makeDecimalRaw64(1000, 0);
        c64 = Util::makeDecimalRaw64(  10, 2);

        ASSERT(!Util::notEqual(a64, b64));
        ASSERT(!Util::notEqual(b64, a64));
        ASSERT(!Util::notEqual(b64, c64));
        ASSERT(!Util::notEqual(c64, b64));
        ASSERT(!Util::notEqual(a64, c64));
        ASSERT(!Util::notEqual(c64, a64));

        a128 = Util::makeDecimalRaw128(   1, 3);
        b128 = Util::makeDecimalRaw128(1000, 0);
        c128 = Util::makeDecimalRaw128(  10, 2);

        ASSERT(!Util::notEqual(a128, b128));
        ASSERT(!Util::notEqual(b128, a128));
        ASSERT(!Util::notEqual(b128, c128));
        ASSERT(!Util::notEqual(c128, b128));
        ASSERT(!Util::notEqual(a128, c128));
        ASSERT(!Util::notEqual(c128, a128));

        // Negative transitivity

        a32 = Util::makeDecimalRaw32(   1, 3);
        b32 = Util::makeDecimalRaw32(1000, 0);
        c32 = Util::makeDecimalRaw32(  20, 2);

        ASSERT(!Util::notEqual(a32, b32));
        ASSERT(!Util::notEqual(b32, a32));
        ASSERT( Util::notEqual(b32, c32));
        ASSERT( Util::notEqual(c32, b32));
        ASSERT( Util::notEqual(a32, c32));
        ASSERT( Util::notEqual(c32, a32));

        a64 = Util::makeDecimalRaw64(   1, 3);
        b64 = Util::makeDecimalRaw64(1000, 0);
        c64 = Util::makeDecimalRaw64(  20, 2);

        ASSERT(!Util::notEqual(a64, b64));
        ASSERT(!Util::notEqual(b64, a64));
        ASSERT( Util::notEqual(b64, c64));
        ASSERT( Util::notEqual(c64, b64));
        ASSERT( Util::notEqual(a64, c64));
        ASSERT( Util::notEqual(c64, a64));

        a128 = Util::makeDecimalRaw128(   1, 3);
        b128 = Util::makeDecimalRaw128(1000, 0);
        c128 = Util::makeDecimalRaw128(  20, 2);

        ASSERT(!Util::notEqual(a128, b128));
        ASSERT(!Util::notEqual(b128, a128));
        ASSERT( Util::notEqual(b128, c128));
        ASSERT( Util::notEqual(c128, b128));
        ASSERT( Util::notEqual(a128, c128));
        ASSERT( Util::notEqual(c128, a128));
    }

    // 'NaN' and 'Inf' testing

    // These tests should be in the same order as Concern #10.

    {
        Util::ValueType32   nan32  = Util::parse32(  "NaN");
        Util::ValueType32  qnan32  = Util::parse32( "qNaN");
        Util::ValueType32  snan32  = Util::parse32( "sNaN");
        Util::ValueType32  pinf32  = Util::parse32( "+Inf");
        Util::ValueType32  ninf32  = Util::parse32( "-Inf");
        Util::ValueType32  test32  = Util::makeDecimalRaw32(42, 1);

        Util::ValueType64   nan64  = Util::parse64(  "NaN");
        Util::ValueType64  qnan64  = Util::parse64( "qNaN");
        Util::ValueType64  snan64  = Util::parse64( "sNaN");
        Util::ValueType64  pinf64  = Util::parse64( "+Inf");
        Util::ValueType64  ninf64  = Util::parse64( "-Inf");
        Util::ValueType64  test64  = Util::makeDecimalRaw64(42, 1);

        Util::ValueType128  nan128 = Util::parse128( "NaN");
        Util::ValueType128 qnan128 = Util::parse128("qNaN");
        Util::ValueType128 snan128 = Util::parse128("sNaN");
        Util::ValueType128 pinf128 = Util::parse128("+Inf");
        Util::ValueType128 ninf128 = Util::parse128("-Inf");
        Util::ValueType128 test128 = Util::makeDecimalRaw128(42, 1);

        // 'NaN' is not notEqual to itself, in any form.

        ASSERT( Util::notEqual( nan32,   nan32));
        ASSERT( Util::notEqual(qnan32,  qnan32));
        errno = 0;
        ASSERT( Util::notEqual(snan32,  snan32));
        ASSERT(EDOM == errno);

        ASSERT( Util::notEqual( nan64,   nan64));
        ASSERT( Util::notEqual(qnan64,  qnan64));
        errno = 0;
        ASSERT( Util::notEqual(snan64,  snan64));
        ASSERT(EDOM == errno);

        ASSERT( Util::notEqual( nan128,  nan128));
        ASSERT( Util::notEqual(qnan128, qnan128));
        errno = 0;
        ASSERT( Util::notEqual(snan128, snan128));
        ASSERT(EDOM == errno);

        // Cross 'NaN' comparisons should all be inequal.

        ASSERT( Util::notEqual( nan32,  qnan32));
        ASSERT( Util::notEqual(qnan32,   nan32));
        ASSERT( Util::notEqual( nan32,  snan32));
        ASSERT( Util::notEqual(snan32,   nan32));
        ASSERT( Util::notEqual(qnan32,  snan32));
        ASSERT( Util::notEqual(snan32,  qnan32));

        ASSERT( Util::notEqual( nan64,  qnan64));
        ASSERT( Util::notEqual(qnan64,   nan64));
        ASSERT( Util::notEqual( nan64,  snan64));
        ASSERT( Util::notEqual(snan64,   nan64));
        ASSERT( Util::notEqual(qnan64,  snan64));
        ASSERT( Util::notEqual(snan64,  qnan64));

        ASSERT( Util::notEqual( nan128, qnan128));
        ASSERT( Util::notEqual(qnan128,  nan128));
        ASSERT( Util::notEqual( nan128, snan128));
        ASSERT( Util::notEqual(snan128,  nan128));
        ASSERT( Util::notEqual(qnan128, snan128));
        ASSERT( Util::notEqual(snan128, qnan128));

        // 'NaN' to value comparisons should be inequal too.

        ASSERT( Util::notEqual( nan32,  test32));
        ASSERT( Util::notEqual(test32,   nan32));
        ASSERT( Util::notEqual(qnan32,  test32));
        ASSERT( Util::notEqual(test32,  qnan32));
        ASSERT( Util::notEqual(snan32,  test32));
        ASSERT( Util::notEqual(test32,  snan32));

        ASSERT( Util::notEqual( nan64,  test64));
        ASSERT( Util::notEqual(test64,   nan64));
        ASSERT( Util::notEqual(qnan64,  test64));
        ASSERT( Util::notEqual(test64,  qnan64));
        ASSERT( Util::notEqual(snan64,  test64));
        ASSERT( Util::notEqual(test64,  snan64));

        ASSERT( Util::notEqual( nan128, test128));
        ASSERT( Util::notEqual(test128,  nan128));
        ASSERT( Util::notEqual(qnan128, test128));
        ASSERT( Util::notEqual(test128, qnan128));
        ASSERT( Util::notEqual(snan128, test128));
        ASSERT( Util::notEqual(test128, snan128));

        // 'Inf's should compare notEqual only when they have different
        // signs

        ASSERT(!Util::notEqual(pinf32,  pinf32));
        ASSERT(!Util::notEqual(ninf32,  ninf32));
        ASSERT( Util::notEqual(pinf32,  ninf32));
        ASSERT( Util::notEqual(ninf32,  pinf32));

        ASSERT(!Util::notEqual(pinf64,  pinf64));
        ASSERT(!Util::notEqual(ninf64,  ninf64));
        ASSERT( Util::notEqual(pinf64,  ninf64));
        ASSERT( Util::notEqual(ninf64,  pinf64));

        ASSERT(!Util::notEqual(pinf128, pinf128));
        ASSERT(!Util::notEqual(ninf128, ninf128));
        ASSERT( Util::notEqual(pinf128, ninf128));
        ASSERT( Util::notEqual(ninf128, pinf128));

        // Value to 'Inf' comparisons should be inequal.

        ASSERT( Util::notEqual(test32,  pinf32));
        ASSERT( Util::notEqual(test32,  ninf32));
        ASSERT( Util::notEqual(pinf32,  test32));
        ASSERT( Util::notEqual(ninf32,  test32));

        ASSERT( Util::notEqual(test64,  pinf64));
        ASSERT( Util::notEqual(test64,  ninf64));
        ASSERT( Util::notEqual(pinf64,  test64));
        ASSERT( Util::notEqual(ninf64,  test64));

        ASSERT( Util::notEqual(test128, pinf128));
        ASSERT( Util::notEqual(test128, ninf128));
        ASSERT( Util::notEqual(pinf128, test128));
        ASSERT( Util::notEqual(ninf128, test128));

        // 'Inf' to 'NaN' comparisons should be inequal.

        ASSERT( Util::notEqual( nan32,  pinf32));
        ASSERT( Util::notEqual( nan32,  ninf32));
        ASSERT( Util::notEqual(qnan32,  pinf32));
        ASSERT( Util::notEqual(qnan32,  ninf32));
        ASSERT( Util::notEqual(snan32,  pinf32));
        ASSERT( Util::notEqual(snan32,  ninf32));
        ASSERT( Util::notEqual(pinf32,   nan32));
        ASSERT( Util::notEqual(ninf32,   nan32));
        ASSERT( Util::notEqual(pinf32,  qnan32));
        ASSERT( Util::notEqual(ninf32,  qnan32));
        ASSERT( Util::notEqual(pinf32,  snan32));
        ASSERT( Util::notEqual(ninf32,  snan32));

        ASSERT( Util::notEqual( nan64,  pinf64));
        ASSERT( Util::notEqual( nan64,  ninf64));
        ASSERT( Util::notEqual(qnan64,  pinf64));
        ASSERT( Util::notEqual(qnan64,  ninf64));
        ASSERT( Util::notEqual(snan64,  pinf64));
        ASSERT( Util::notEqual(snan64,  ninf64));
        ASSERT( Util::notEqual(pinf64,   nan64));
        ASSERT( Util::notEqual(ninf64,   nan64));
        ASSERT( Util::notEqual(pinf64,  qnan64));
        ASSERT( Util::notEqual(ninf64,  qnan64));
        ASSERT( Util::notEqual(pinf64,  snan64));
        ASSERT( Util::notEqual(ninf64,  snan64));

        ASSERT( Util::notEqual( nan128, pinf128));
        ASSERT( Util::notEqual( nan128, ninf128));
        ASSERT( Util::notEqual(qnan128, pinf128));
        ASSERT( Util::notEqual(qnan128, ninf128));
        ASSERT( Util::notEqual(snan128, pinf128));
        ASSERT( Util::notEqual(snan128, ninf128));
        ASSERT( Util::notEqual(pinf128,  nan128));
        ASSERT( Util::notEqual(ninf128,  nan128));
        ASSERT( Util::notEqual(pinf128, qnan128));
        ASSERT( Util::notEqual(ninf128, qnan128));
        ASSERT( Util::notEqual(pinf128, snan128));
        ASSERT( Util::notEqual(ninf128, snan128));
    }
}

void TestDriver::testCase3()
{
    // ------------------------------------------------------------------------
    // EQUALITY COMPARISON 'Util::equal'
    //
    // Concerns:
    //:  1 'equal' should return true if the bit patterns are the same (and are
    //:    not a bit pattern representing a 'NaN').
    //:
    //:  2 'equal' should return true if the bit patterns are different, but
    //:    represent the same value.  I.e. '10e0' should be equal to '1e1'.
    //:
    //:  3 Values which differ by only one of sign, exponent, or mantissa
    //:    should not be equal.
    //:
    //:  4 'NaN' values should never be equal.
    //:
    //:  5 The implementation of 'equal' normally would be a forwarding
    //:    function (to the underlying implementation), but some
    //:    implementations require a call to a helper function to determine
    //:    value.  This means that we don't have to aggressively test this
    //:    function, but should perform more than a cursory forwarding test.
    //:    (This will result in more than a simple forwarding test.)
    //:
    //:  6 Equality is a "Commutative" operation:
    //:       'A == B' implies 'B == A'
    //:    (Commutative property.)
    //:
    //:  7 Equality is a "Commutative" operation in the negative:
    //:       'A != B' implies 'B != A'
    //:    (Commutative property.)
    //:
    //:  8 Any two things equal to a third are equal to each other:
    //:       'A == B' and 'B == C' implies 'A == C'.
    //:    (Transitive property.)
    //:
    //:  9 Any two things equal to each other are both inequal to an inequal
    //:    third:
    //:       'A == B' and 'B != C' implies 'A != C'
    //:    (Transitive property.)
    //:
    //: 10 'NaN' and 'Inf' states are excluded from these rules and instead
    //:    have the following properties:
    //:
    //:     1  'NaN' !=  'NaN'
    //:     2  value !=  'NaN'
    //:     3  'NaN' !=  value
    //:     4 +'Inf' == +'Inf'
    //:     5 -'Inf' == -'Inf'
    //:     6 +'Inf' != -'Inf'
    //:     7 -'Inf' != +'Inf'
    //:     8  value != +'Inf'
    //:     9  value != -'Inf'
    //:    10 +'Inf' !=  value
    //:    11 -'Inf' !=  value
    //:    12  'NaN' != +'Inf'
    //:    13  'NaN' != -'Inf'
    //:    14 +'Inf' !=  'NaN'
    //:    15 -'Inf' !=  'NaN'
    //:
    //: 11 Equality tests more than identity (same 'this' pointer).
    //
    // Plan:
    //:  1 Myriad values will be tested for equality and inequality with
    //:    slightly altered values.  ('A != A + 1', and 'A + 1 != A', for
    //:    example)
    //:
    //:  2 All equality, and inequality tests will be tested with both
    //:    possible orderings to check the Commutative property.
    //:
    //:  3 Values will be tested for equality with copies of themselves
    //
    // Testing:
    //   equal(ValueType32,  ValueType32)
    //   equal(ValueType64,  ValueType64)
    //   equal(ValueType128, ValueType128)
    // --------------------------------------------------------------------


    if (verbose) cout << endl
                      << "EQUALITY COMPARISON 'Util::equal'" << endl
                      << "=================================" << endl;

    // Basic value comparison testing

    {

        Util::ValueType32  test32;
        Util::ValueType64  test64;
        Util::ValueType128 test128;

        Util::ValueType32  same32;
        Util::ValueType64  same64;
        Util::ValueType128 same128;

        Util::ValueType32  negated32;
        Util::ValueType64  negated64;
        Util::ValueType128 negated128;

        Util::ValueType32  incremented32;
        Util::ValueType64  incremented64;
        Util::ValueType128 incremented128;

        Util::ValueType32  exponentChanged32;
        Util::ValueType64  exponentChanged64;
        Util::ValueType128 exponentChanged128;

                //    0e0

                // (All 0's are special cases which only differ by mantissa
                // value not by exponent or sign.)

        test32 = Util::makeDecimalRaw32(0, 0);
        same32 = Util::makeDecimalRaw32(0, 0);
        incremented32 = Util::makeDecimalRaw32(1, 0);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, 0);
        same64 = Util::makeDecimalRaw64(0, 0);
        incremented64 = Util::makeDecimalRaw64(1, 0);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, 0);
        same128 = Util::makeDecimalRaw128(0, 0);
        incremented128 = Util::makeDecimalRaw128(1, 0);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));

                //    7e0

        test32 = Util::makeDecimalRaw32(7, 0);
        same32 = Util::makeDecimalRaw32(7, 0);
        negated32 = Util::makeDecimalRaw32(-7, 0);
        incremented32 = Util::makeDecimalRaw32(8, 0);
        exponentChanged32 = Util::makeDecimalRaw32(7, 2);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, 0);
        same64 = Util::makeDecimalRaw64(7, 0);
        negated64 = Util::makeDecimalRaw64(-7, 0);
        incremented64 = Util::makeDecimalRaw64(8, 0);
        exponentChanged64 = Util::makeDecimalRaw64(7, 2);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, 0);
        same128 = Util::makeDecimalRaw128(7, 0);
        negated128 = Util::makeDecimalRaw128(-7, 0);
        incremented128 = Util::makeDecimalRaw128(8, 0);
        exponentChanged128 = Util::makeDecimalRaw128(7, 2);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //  100e0

        test32 = Util::makeDecimalRaw32(100, 0);
        same32 = Util::makeDecimalRaw32(100, 0);
        negated32 = Util::makeDecimalRaw32(-100, 0);
        incremented32 = Util::makeDecimalRaw32(101, 0);
        exponentChanged32 = Util::makeDecimalRaw32(100, 2);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, 0);
        same64 = Util::makeDecimalRaw64(100, 0);
        negated64 = Util::makeDecimalRaw64(-100, 0);
        incremented64 = Util::makeDecimalRaw64(101, 0);
        exponentChanged64 = Util::makeDecimalRaw64(100, 2);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, 0);
        same128 = Util::makeDecimalRaw128(100, 0);
        negated128 = Util::makeDecimalRaw128(-100, 0);
        incremented128 = Util::makeDecimalRaw128(101, 0);
        exponentChanged128 = Util::makeDecimalRaw128(100, 2);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //   -7e0

        test32 = Util::makeDecimalRaw32(-7, 0);
        same32 = Util::makeDecimalRaw32(-7, 0);
        negated32 = Util::makeDecimalRaw32(7, 0);
        incremented32 = Util::makeDecimalRaw32(-6, 0);
        exponentChanged32 = Util::makeDecimalRaw32(-7, 2);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, 0);
        same64 = Util::makeDecimalRaw64(-7, 0);
        negated64 = Util::makeDecimalRaw64(7, 0);
        incremented64 = Util::makeDecimalRaw64(-6, 0);
        exponentChanged64 = Util::makeDecimalRaw64(-7, 2);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, 0);
        same128 = Util::makeDecimalRaw128(-7, 0);
        negated128 = Util::makeDecimalRaw128(7, 0);
        incremented128 = Util::makeDecimalRaw128(-6, 0);
        exponentChanged128 = Util::makeDecimalRaw128(-7, 2);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                // -100e0

        test32 = Util::makeDecimalRaw32(-100, 0);
        same32 = Util::makeDecimalRaw32(-100, 0);
        negated32 = Util::makeDecimalRaw32(100, 0);
        incremented32 = Util::makeDecimalRaw32(-99, 0);
        exponentChanged32 = Util::makeDecimalRaw32(-100, 2);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, 0);
        same64 = Util::makeDecimalRaw64(-100, 0);
        negated64 = Util::makeDecimalRaw64(100, 0);
        incremented64 = Util::makeDecimalRaw64(-99, 0);
        exponentChanged64 = Util::makeDecimalRaw64(-100, 2);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, 0);
        same128 = Util::makeDecimalRaw128(-100, 0);
        negated128 = Util::makeDecimalRaw128(100, 0);
        incremented128 = Util::makeDecimalRaw128(-99, 0);
        exponentChanged128 = Util::makeDecimalRaw128(-100, 2);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //    0e3

        test32 = Util::makeDecimalRaw32(0, 3);
        same32 = Util::makeDecimalRaw32(0, 3);
        incremented32 = Util::makeDecimalRaw32(1, 3);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, 3);
        same64 = Util::makeDecimalRaw64(0, 3);
        incremented64 = Util::makeDecimalRaw64(1, 3);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, 3);
        same128 = Util::makeDecimalRaw128(0, 3);
        incremented128 = Util::makeDecimalRaw128(1, 3);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));

                //    7e3

        test32 = Util::makeDecimalRaw32(7, 3);
        same32 = Util::makeDecimalRaw32(7, 3);
        negated32 = Util::makeDecimalRaw32(-7, 3);
        incremented32 = Util::makeDecimalRaw32(8, 3);
        exponentChanged32 = Util::makeDecimalRaw32(7, 5);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, 3);
        same64 = Util::makeDecimalRaw64(7, 3);
        negated64 = Util::makeDecimalRaw64(-7, 3);
        incremented64 = Util::makeDecimalRaw64(8, 3);
        exponentChanged64 = Util::makeDecimalRaw64(7, 5);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, 3);
        same128 = Util::makeDecimalRaw128(7, 3);
        negated128 = Util::makeDecimalRaw128(-7, 3);
        incremented128 = Util::makeDecimalRaw128(8, 3);
        exponentChanged128 = Util::makeDecimalRaw128(7, 5);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //  100e3

        test32 = Util::makeDecimalRaw32(100, 3);
        same32 = Util::makeDecimalRaw32(100, 3);
        negated32 = Util::makeDecimalRaw32(-100, 3);
        incremented32 = Util::makeDecimalRaw32(101, 3);
        exponentChanged32 = Util::makeDecimalRaw32(100, 5);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, 3);
        same64 = Util::makeDecimalRaw64(100, 3);
        negated64 = Util::makeDecimalRaw64(-100, 3);
        incremented64 = Util::makeDecimalRaw64(101, 3);
        exponentChanged64 = Util::makeDecimalRaw64(100, 5);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, 3);
        same128 = Util::makeDecimalRaw128(100, 3);
        negated128 = Util::makeDecimalRaw128(-100, 3);
        incremented128 = Util::makeDecimalRaw128(101, 3);
        exponentChanged128 = Util::makeDecimalRaw128(100, 5);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //   -7e3

        test32 = Util::makeDecimalRaw32(-7, 3);
        same32 = Util::makeDecimalRaw32(-7, 3);
        negated32 = Util::makeDecimalRaw32(7, 3);
        incremented32 = Util::makeDecimalRaw32(-6, 3);
        exponentChanged32 = Util::makeDecimalRaw32(-7, 5);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, 3);
        same64 = Util::makeDecimalRaw64(-7, 3);
        negated64 = Util::makeDecimalRaw64(7, 3);
        incremented64 = Util::makeDecimalRaw64(-6, 3);
        exponentChanged64 = Util::makeDecimalRaw64(-7, 5);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, 3);
        same128 = Util::makeDecimalRaw128(-7, 3);
        negated128 = Util::makeDecimalRaw128(7, 3);
        incremented128 = Util::makeDecimalRaw128(-6, 3);
        exponentChanged128 = Util::makeDecimalRaw128(-7, 5);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                // -100e3

        test32 = Util::makeDecimalRaw32(-100, 3);
        same32 = Util::makeDecimalRaw32(-100, 3);
        negated32 = Util::makeDecimalRaw32(100, 3);
        incremented32 = Util::makeDecimalRaw32(-99, 3);
        exponentChanged32 = Util::makeDecimalRaw32(-100, 5);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, 3);
        same64 = Util::makeDecimalRaw64(-100, 3);
        negated64 = Util::makeDecimalRaw64(100, 3);
        incremented64 = Util::makeDecimalRaw64(-99, 3);
        exponentChanged64 = Util::makeDecimalRaw64(-100, 5);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, 3);
        same128 = Util::makeDecimalRaw128(-100, 3);
        negated128 = Util::makeDecimalRaw128(100, 3);
        incremented128 = Util::makeDecimalRaw128(-99, 3);
        exponentChanged128 = Util::makeDecimalRaw128(-100, 5);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //    0e-5

        test32 = Util::makeDecimalRaw32(0, -5);
        same32 = Util::makeDecimalRaw32(0, -5);
        incremented32 = Util::makeDecimalRaw32(1, -5);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));

        test64 = Util::makeDecimalRaw64(0, -5);
        same64 = Util::makeDecimalRaw64(0, -5);
        incremented64 = Util::makeDecimalRaw64(1, -5);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));

        test128 = Util::makeDecimalRaw128(0, -5);
        same128 = Util::makeDecimalRaw128(0, -5);
        incremented128 = Util::makeDecimalRaw128(1, -5);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));

                //    7e-5

        test32 = Util::makeDecimalRaw32(7, -5);
        same32 = Util::makeDecimalRaw32(7, -5);
        negated32 = Util::makeDecimalRaw32(-7, -5);
        incremented32 = Util::makeDecimalRaw32(8, -5);
        exponentChanged32 = Util::makeDecimalRaw32(7, -3);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(7, -5);
        same64 = Util::makeDecimalRaw64(7, -5);
        negated64 = Util::makeDecimalRaw64(-7, -5);
        incremented64 = Util::makeDecimalRaw64(8, -5);
        exponentChanged64 = Util::makeDecimalRaw64(7, -3);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(7, -5);
        same128 = Util::makeDecimalRaw128(7, -5);
        negated128 = Util::makeDecimalRaw128(-7, -5);
        incremented128 = Util::makeDecimalRaw128(8, -5);
        exponentChanged128 = Util::makeDecimalRaw128(7, -3);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //  100e-5

        test32 = Util::makeDecimalRaw32(100, -5);
        same32 = Util::makeDecimalRaw32(100, -5);
        negated32 = Util::makeDecimalRaw32(-100, -5);
        incremented32 = Util::makeDecimalRaw32(101, -5);
        exponentChanged32 = Util::makeDecimalRaw32(100, -3);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(100, -5);
        same64 = Util::makeDecimalRaw64(100, -5);
        negated64 = Util::makeDecimalRaw64(-100, -5);
        incremented64 = Util::makeDecimalRaw64(101, -5);
        exponentChanged64 = Util::makeDecimalRaw64(100, -3);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(100, -5);
        same128 = Util::makeDecimalRaw128(100, -5);
        negated128 = Util::makeDecimalRaw128(-100, -5);
        incremented128 = Util::makeDecimalRaw128(101, -5);
        exponentChanged128 = Util::makeDecimalRaw128(100, -3);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                //   -7e-5

        test32 = Util::makeDecimalRaw32(-7, -5);
        same32 = Util::makeDecimalRaw32(-7, -5);
        negated32 = Util::makeDecimalRaw32(7, -5);
        incremented32 = Util::makeDecimalRaw32(-6, -5);
        exponentChanged32 = Util::makeDecimalRaw32(-7, -3);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-7, -5);
        same64 = Util::makeDecimalRaw64(-7, -5);
        negated64 = Util::makeDecimalRaw64(7, -5);
        incremented64 = Util::makeDecimalRaw64(-6, -5);
        exponentChanged64 = Util::makeDecimalRaw64(-7, -3);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-7, -5);
        same128 = Util::makeDecimalRaw128(-7, -5);
        negated128 = Util::makeDecimalRaw128(7, -5);
        incremented128 = Util::makeDecimalRaw128(-6, -5);
        exponentChanged128 = Util::makeDecimalRaw128(-7, -3);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

                // -100e-5

        test32 = Util::makeDecimalRaw32(-100, -5);
        same32 = Util::makeDecimalRaw32(-100, -5);
        negated32 = Util::makeDecimalRaw32(100, -5);
        incremented32 = Util::makeDecimalRaw32(-99, -5);
        exponentChanged32 = Util::makeDecimalRaw32(-100, -3);
        ASSERT( Util::equal(test32, test32));
        ASSERT( Util::equal(same32, test32));
        ASSERT( Util::equal(test32, same32));
        ASSERT(!Util::equal(negated32, test32));
        ASSERT(!Util::equal(test32, negated32));
        ASSERT(!Util::equal(incremented32, test32));
        ASSERT(!Util::equal(test32, incremented32));
        ASSERT(!Util::equal(exponentChanged32, test32));
        ASSERT(!Util::equal(test32, exponentChanged32));

        test64 = Util::makeDecimalRaw64(-100, -5);
        same64 = Util::makeDecimalRaw64(-100, -5);
        negated64 = Util::makeDecimalRaw64(100, -5);
        incremented64 = Util::makeDecimalRaw64(-99, -5);
        exponentChanged64 = Util::makeDecimalRaw64(-100, -3);
        ASSERT( Util::equal(test64, test64));
        ASSERT( Util::equal(same64, test64));
        ASSERT( Util::equal(test64, same64));
        ASSERT(!Util::equal(negated64, test64));
        ASSERT(!Util::equal(test64, negated64));
        ASSERT(!Util::equal(incremented64, test64));
        ASSERT(!Util::equal(test64, incremented64));
        ASSERT(!Util::equal(exponentChanged64, test64));
        ASSERT(!Util::equal(test64, exponentChanged64));

        test128 = Util::makeDecimalRaw128(-100, -5);
        same128 = Util::makeDecimalRaw128(-100, -5);
        negated128 = Util::makeDecimalRaw128(100, -5);
        incremented128 = Util::makeDecimalRaw128(-99, -5);
        exponentChanged128 = Util::makeDecimalRaw128(-100, -3);
        ASSERT( Util::equal(test128, test128));
        ASSERT( Util::equal(same128, test128));
        ASSERT( Util::equal(test128, same128));
        ASSERT(!Util::equal(negated128, test128));
        ASSERT(!Util::equal(test128, negated128));
        ASSERT(!Util::equal(incremented128, test128));
        ASSERT(!Util::equal(test128, incremented128));
        ASSERT(!Util::equal(exponentChanged128, test128));
        ASSERT(!Util::equal(test128, exponentChanged128));

    }

    // Non bitwise equal testing:

    {
        Util::ValueType32 test32;
        Util::ValueType32 alt32;

        Util::ValueType64 test64;
        Util::ValueType64 alt64;

        Util::ValueType128 test128;
        Util::ValueType128 alt128;

                    // 0

        test32 = Util::makeDecimalRaw32(0, 0);
        alt32  = Util::makeDecimalRaw32(0, 5);

        ASSERT( Util::equal(test32,  alt32));
        ASSERT( Util::equal( alt32, test32));

        test64 = Util::makeDecimalRaw64(0, 0);
        alt64  = Util::makeDecimalRaw64(0, 5);

        ASSERT( Util::equal(test64,  alt64));
        ASSERT( Util::equal( alt64, test64));

        test128 = Util::makeDecimalRaw128(0, 0);
        alt128  = Util::makeDecimalRaw128(0, 5);

        ASSERT( Util::equal(test128,  alt128));
        ASSERT( Util::equal( alt128, test128));

                    // 700 vs 7e2

        test32 = Util::makeDecimalRaw32(700, 0);
        alt32  = Util::makeDecimalRaw32(7,   2);

        ASSERT( Util::equal(test32,  alt32));
        ASSERT( Util::equal( alt32, test32));

        test64 = Util::makeDecimalRaw64(700, 0);
        alt64  = Util::makeDecimalRaw64(7,   2);

        ASSERT( Util::equal(test64,  alt64));
        ASSERT( Util::equal( alt64, test64));

        test128 = Util::makeDecimalRaw128(700, 0);
        alt128  = Util::makeDecimalRaw128(7,   2);

        ASSERT( Util::equal(test128,  alt128));
        ASSERT( Util::equal( alt128, test128));
    }

    // Transitivity tests

    {
        // Positive transitivity

        Util::ValueType32 a32;
        Util::ValueType32 b32;
        Util::ValueType32 c32;

        Util::ValueType64 a64;
        Util::ValueType64 b64;
        Util::ValueType64 c64;

        Util::ValueType128 a128;
        Util::ValueType128 b128;
        Util::ValueType128 c128;

        a32 = Util::makeDecimalRaw32(   1, 3);
        b32 = Util::makeDecimalRaw32(1000, 0);
        c32 = Util::makeDecimalRaw32(  10, 2);

        ASSERT( Util::equal(a32, b32));
        ASSERT( Util::equal(b32, a32));
        ASSERT( Util::equal(b32, c32));
        ASSERT( Util::equal(c32, b32));
        ASSERT( Util::equal(a32, c32));
        ASSERT( Util::equal(c32, a32));

        a64 = Util::makeDecimalRaw64(   1, 3);
        b64 = Util::makeDecimalRaw64(1000, 0);
        c64 = Util::makeDecimalRaw64(  10, 2);

        ASSERT( Util::equal(a64, b64));
        ASSERT( Util::equal(b64, a64));
        ASSERT( Util::equal(b64, c64));
        ASSERT( Util::equal(c64, b64));
        ASSERT( Util::equal(a64, c64));
        ASSERT( Util::equal(c64, a64));

        a128 = Util::makeDecimalRaw128(   1, 3);
        b128 = Util::makeDecimalRaw128(1000, 0);
        c128 = Util::makeDecimalRaw128(  10, 2);

        ASSERT( Util::equal(a128, b128));
        ASSERT( Util::equal(b128, a128));
        ASSERT( Util::equal(b128, c128));
        ASSERT( Util::equal(c128, b128));
        ASSERT( Util::equal(a128, c128));
        ASSERT( Util::equal(c128, a128));

        // Negative transitivity

        a32 = Util::makeDecimalRaw32(   1, 3);
        b32 = Util::makeDecimalRaw32(1000, 0);
        c32 = Util::makeDecimalRaw32(  20, 2);

        ASSERT( Util::equal(a32, b32));
        ASSERT( Util::equal(b32, a32));
        ASSERT(!Util::equal(b32, c32));
        ASSERT(!Util::equal(c32, b32));
        ASSERT(!Util::equal(a32, c32));
        ASSERT(!Util::equal(c32, a32));

        a64 = Util::makeDecimalRaw64(   1, 3);
        b64 = Util::makeDecimalRaw64(1000, 0);
        c64 = Util::makeDecimalRaw64(  20, 2);

        ASSERT( Util::equal(a64, b64));
        ASSERT( Util::equal(b64, a64));
        ASSERT(!Util::equal(b64, c64));
        ASSERT(!Util::equal(c64, b64));
        ASSERT(!Util::equal(a64, c64));
        ASSERT(!Util::equal(c64, a64));

        a128 = Util::makeDecimalRaw128(   1, 3);
        b128 = Util::makeDecimalRaw128(1000, 0);
        c128 = Util::makeDecimalRaw128(  20, 2);

        ASSERT( Util::equal(a128, b128));
        ASSERT( Util::equal(b128, a128));
        ASSERT(!Util::equal(b128, c128));
        ASSERT(!Util::equal(c128, b128));
        ASSERT(!Util::equal(a128, c128));
        ASSERT(!Util::equal(c128, a128));
    }

    // 'NaN' and 'Inf' testing

    // These tests should be in the same order as Concern #10.

    {
        Util::ValueType32   nan32  = Util::parse32(  "NaN");
        Util::ValueType32  qnan32  = Util::parse32( "qNaN");
        Util::ValueType32  snan32  = Util::parse32( "sNaN");
        Util::ValueType32  pinf32  = Util::parse32( "+Inf");
        Util::ValueType32  ninf32  = Util::parse32( "-Inf");
        Util::ValueType32  test32  = Util::makeDecimalRaw32(42, 1);

        Util::ValueType64   nan64  = Util::parse64(  "NaN");
        Util::ValueType64  qnan64  = Util::parse64( "qNaN");
        Util::ValueType64  snan64  = Util::parse64( "sNaN");
        Util::ValueType64  pinf64  = Util::parse64( "+Inf");
        Util::ValueType64  ninf64  = Util::parse64( "-Inf");
        Util::ValueType64  test64  = Util::makeDecimalRaw64(42, 1);

        Util::ValueType128  nan128 = Util::parse128( "NaN");
        Util::ValueType128 qnan128 = Util::parse128("qNaN");
        Util::ValueType128 snan128 = Util::parse128("sNaN");
        Util::ValueType128 pinf128 = Util::parse128("+Inf");
        Util::ValueType128 ninf128 = Util::parse128("-Inf");
        Util::ValueType128 test128 = Util::makeDecimalRaw128(42, 1);

        // 'NaN' is not equal to itself, in any form.

        ASSERT(!Util::equal( nan32,   nan32));
        ASSERT(!Util::equal(qnan32,  qnan32));
        errno = 0;
        ASSERT(!Util::equal(snan32,  snan32));
        ASSERT(EDOM == errno);

        ASSERT(!Util::equal( nan64,   nan64));
        ASSERT(!Util::equal(qnan64,  qnan64));
        errno = 0;
        ASSERT(!Util::equal(snan64,  snan64));
        ASSERT(EDOM == errno);

        ASSERT(!Util::equal( nan128,  nan128));
        ASSERT(!Util::equal(qnan128, qnan128));
        errno = 0;
        ASSERT(!Util::equal(snan128, snan128));
        ASSERT(EDOM == errno);

        // Cross 'NaN' comparisons should all be false.

        ASSERT(!Util::equal( nan32,  qnan32));
        ASSERT(!Util::equal(qnan32,   nan32));
        ASSERT(!Util::equal( nan32,  snan32));
        ASSERT(!Util::equal(snan32,   nan32));
        ASSERT(!Util::equal(qnan32,  snan32));
        ASSERT(!Util::equal(snan32,  qnan32));

        ASSERT(!Util::equal( nan64,  qnan64));
        ASSERT(!Util::equal(qnan64,   nan64));
        ASSERT(!Util::equal( nan64,  snan64));
        ASSERT(!Util::equal(snan64,   nan64));
        ASSERT(!Util::equal(qnan64,  snan64));
        ASSERT(!Util::equal(snan64,  qnan64));

        ASSERT(!Util::equal( nan128, qnan128));
        ASSERT(!Util::equal(qnan128,  nan128));
        ASSERT(!Util::equal( nan128, snan128));
        ASSERT(!Util::equal(snan128,  nan128));
        ASSERT(!Util::equal(qnan128, snan128));
        ASSERT(!Util::equal(snan128, qnan128));

        // 'NaN' to value comparisons should be false too.

        ASSERT(!Util::equal( nan32,  test32));
        ASSERT(!Util::equal(test32,   nan32));
        ASSERT(!Util::equal(qnan32,  test32));
        ASSERT(!Util::equal(test32,  qnan32));
        ASSERT(!Util::equal(snan32,  test32));
        ASSERT(!Util::equal(test32,  snan32));

        ASSERT(!Util::equal( nan64,  test64));
        ASSERT(!Util::equal(test64,   nan64));
        ASSERT(!Util::equal(qnan64,  test64));
        ASSERT(!Util::equal(test64,  qnan64));
        ASSERT(!Util::equal(snan64,  test64));
        ASSERT(!Util::equal(test64,  snan64));

        ASSERT(!Util::equal( nan128, test128));
        ASSERT(!Util::equal(test128,  nan128));
        ASSERT(!Util::equal(qnan128, test128));
        ASSERT(!Util::equal(test128, qnan128));
        ASSERT(!Util::equal(snan128, test128));
        ASSERT(!Util::equal(test128, snan128));

        // 'Inf's should compare equal only when they have the same sign.

        ASSERT( Util::equal(pinf32,  pinf32));
        ASSERT( Util::equal(ninf32,  ninf32));
        ASSERT(!Util::equal(pinf32,  ninf32));
        ASSERT(!Util::equal(ninf32,  pinf32));

        ASSERT( Util::equal(pinf64,  pinf64));
        ASSERT( Util::equal(ninf64,  ninf64));
        ASSERT(!Util::equal(pinf64,  ninf64));
        ASSERT(!Util::equal(ninf64,  pinf64));

        ASSERT( Util::equal(pinf128, pinf128));
        ASSERT( Util::equal(ninf128, ninf128));
        ASSERT(!Util::equal(pinf128, ninf128));
        ASSERT(!Util::equal(ninf128, pinf128));

        // Value to 'Inf' comparisons should be false.

        ASSERT(!Util::equal(test32,  pinf32));
        ASSERT(!Util::equal(test32,  ninf32));
        ASSERT(!Util::equal(pinf32,  test32));
        ASSERT(!Util::equal(ninf32,  test32));

        ASSERT(!Util::equal(test64,  pinf64));
        ASSERT(!Util::equal(test64,  ninf64));
        ASSERT(!Util::equal(pinf64,  test64));
        ASSERT(!Util::equal(ninf64,  test64));

        ASSERT(!Util::equal(test128, pinf128));
        ASSERT(!Util::equal(test128, ninf128));
        ASSERT(!Util::equal(pinf128, test128));
        ASSERT(!Util::equal(ninf128, test128));

        // 'Inf' to 'NaN' comparisons should be false.

        ASSERT(!Util::equal( nan32,  pinf32));
        ASSERT(!Util::equal( nan32,  ninf32));
        ASSERT(!Util::equal(qnan32,  pinf32));
        ASSERT(!Util::equal(qnan32,  ninf32));
        ASSERT(!Util::equal(snan32,  pinf32));
        ASSERT(!Util::equal(snan32,  ninf32));
        ASSERT(!Util::equal(pinf32,   nan32));
        ASSERT(!Util::equal(ninf32,   nan32));
        ASSERT(!Util::equal(pinf32,  qnan32));
        ASSERT(!Util::equal(ninf32,  qnan32));
        ASSERT(!Util::equal(pinf32,  snan32));
        ASSERT(!Util::equal(ninf32,  snan32));

        ASSERT(!Util::equal( nan64,  pinf64));
        ASSERT(!Util::equal( nan64,  ninf64));
        ASSERT(!Util::equal(qnan64,  pinf64));
        ASSERT(!Util::equal(qnan64,  ninf64));
        ASSERT(!Util::equal(snan64,  pinf64));
        ASSERT(!Util::equal(snan64,  ninf64));
        ASSERT(!Util::equal(pinf64,   nan64));
        ASSERT(!Util::equal(ninf64,   nan64));
        ASSERT(!Util::equal(pinf64,  qnan64));
        ASSERT(!Util::equal(ninf64,  qnan64));
        ASSERT(!Util::equal(pinf64,  snan64));
        ASSERT(!Util::equal(ninf64,  snan64));

        ASSERT(!Util::equal( nan128, pinf128));
        ASSERT(!Util::equal( nan128, ninf128));
        ASSERT(!Util::equal(qnan128, pinf128));
        ASSERT(!Util::equal(qnan128, ninf128));
        ASSERT(!Util::equal(snan128, pinf128));
        ASSERT(!Util::equal(snan128, ninf128));
        ASSERT(!Util::equal(pinf128,  nan128));
        ASSERT(!Util::equal(ninf128,  nan128));
        ASSERT(!Util::equal(pinf128, qnan128));
        ASSERT(!Util::equal(ninf128, qnan128));
        ASSERT(!Util::equal(pinf128, snan128));
        ASSERT(!Util::equal(ninf128, snan128));
    }
}

void TestDriver::testCase2()
{
    // ------------------------------------------------------------------------
    // TESTING 'makeDecimalRaw'
    //
    // Concerns:
    //: 1 'makeDecimalRawXX' constructs a decimal floating point value having
    //:   the specified mantissa and exponent, with no rounding.
    //:
    //: 2 The correctness of the conversion of each 3-digit group (or declet)
    //:   into a 10-bit binary-encoded declet.  Note that this is superfluous
    //:   on BID architectures, but causes no significant slowdown.
    //:
    //: 3 The conversion of each 3-digit declet into a 10-bit binary-encoded
    //:   declet does not intefere each other.
    //:
    //: 4 The combination field is correctly computed given the leading digit
    //:   of the mantissa and the exponent.
    //:
    //: 5 'makeDecimalRawXX' asserts in the right build modes for undefined
    //:   behavior.
    //:
    //: 6 'makeDecimalRawXX' generates expected values.
    //
    // Plan:
    //: 1 Test 'makeDecimalRawXX' contract using
    //:   'AssertFailureHandlerGuard' and 'BSLS_ASSERTTEST_ASSERT_OPT_FAIL'
    //:   (C-5)
    //:
    //: 2 Test each overload of each 'makeDecimalRawXX' by representing the
    //:   mantissa in a string format and parsing in each intergral type.
    //:   (C-1..4, 6)
    //:
    //: 3 Test a mantissa of each length in base 10.  (C-1..4, 6)
    //:
    //: 4 Test that 'makeDecimalRawXX' returns the same value as the decimal
    //:   created by invoking the decNumber constructors using binary-coded
    //:   decimals.  (C-1..4, 6)
    //
    // Testing:
    //   makeDecimalRaw32 (                   int, int)
    //   makeDecimalRaw64 (unsigned long long int, int)
    //   makeDecimalRaw64 (         long long int, int)
    //   makeDecimalRaw64 (unsigned           int, int)
    //   makeDecimalRaw64 (                   int, int)
    //   makeDecimalRaw128(unsigned long long int, int)
    //   makeDecimalRaw128(         long long int, int)
    //   makeDecimalRaw128(unsigned           int, int)
    //   makeDecimalRaw128(                   int, int)
    // ------------------------------------------------------------------------

    if (verbose) cout << endl
                      << "TESTING 'makeDecimalRaw'" << endl
                      << "========================" << endl;
    // Test that with any of a set of exponents, we can create values with
    // mantissas from 1 to 16 digit for 32-bit Decimal values
    {
        Util::ValueType32 test;
        Util::ValueType32 witnessParse;


                    // 0e0

        test             =    Util::makeDecimalRaw32( 0,0);
        witnessParse     =             Util::parse32("0e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 7e0

        test             =    Util::makeDecimalRaw32( 7,0);
        witnessParse     =             Util::parse32("7e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 52e0

        test             =    Util::makeDecimalRaw32( 52,0);
        witnessParse     =             Util::parse32("52e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose) cout << "makeDecimalRaw32, mantissa num: "
                                  << t_m << ", " << mantissas[t_m] << endl;
            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose) cout << "makeDecimalRaw32, exponent num: "
                                      << t_e << ", "
                                      << exponents[t_e] << endl;
                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];


                if (-9999999 <= mantissa && mantissa <= 9999999
                 && -101     <= exponent && exponent <= 90) {
                    int intMantissa = static_cast<int>(mantissa);

                    bsl::string parseString = makeParseString(
                                                    intMantissa, exponent);

                    test = Util::makeDecimalRaw32(intMantissa, exponent);

                    witnessParse = Util::parse32(parseString.c_str());

                    LOOP5_ASSERT(t_m, t_e, mantissa, exponent, parseString,
                     !bsl::memcmp(&test, &witnessParse,     sizeof(test)));
                }
            }
        }
    }

    // Test that with any of a set of exponents, we can create values with
    // mantissas from 1 to 16 digit for 64-bit Decimal values
    {
        Util::ValueType64 test;
        Util::ValueType64 witnessParse;

                    // 0e0

        test             =    Util::makeDecimalRaw64( 0,0);
        witnessParse     =             Util::parse64("0e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 7e0

        test             =    Util::makeDecimalRaw64( 7,0);
        witnessParse     =             Util::parse64("7e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 52e0

        test             =    Util::makeDecimalRaw64( 52,0);
        witnessParse     =             Util::parse64("52e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose) cout << "makeDecimalRaw64, mantissa num: "
                                  << t_m << ", " << mantissas[t_m] << endl;
            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose) cout << "makeDecimalRaw64, exponent num: "
                                      << t_e << ", "
                                      << exponents[t_e] << endl;
                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (mantissa <= bsl::numeric_limits<int>::min()
                 && mantissa <= bsl::numeric_limits<int>::max()) {
                    int intMantissa = static_cast<int>(mantissa);

                    bsl::string parseString = makeParseString(intMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw64(intMantissa, exponent);
                    witnessParse = Util::parse64(parseString.c_str());

                    LOOP5_ASSERT(t_m,         t_e,
                                 intMantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }

                if (0ll      <= mantissa
                 && mantissa <= bsl::numeric_limits<unsigned>::max()) {
                    unsigned uMantissa = static_cast<unsigned>(mantissa);

                    bsl::string parseString = makeParseString(uMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw64(uMantissa, exponent);
                    witnessParse = Util::parse64(parseString.c_str());

                    LOOP5_ASSERT(t_m,       t_e,
                                 uMantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }

                if (0ll      <= mantissa) {
                    // And mantissa <= ULONGLONG_MAX.

                    unsigned long long ullMantissa =
                              static_cast<unsigned long long>(mantissa);

                    bsl::string parseString = makeParseString(ullMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw64(ullMantissa, exponent);
                    witnessParse = Util::parse64(parseString.c_str());

                    LOOP5_ASSERT(t_m,         t_e,
                                 ullMantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }

                if (mantissa <= bsl::numeric_limits<long long>::max() &&
                    mantissa >= bsl::numeric_limits<long long>::min()) {
                    bsl::string parseString = makeParseString(mantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw64(mantissa, exponent);
                    witnessParse = Util::parse64(parseString.c_str());

                    LOOP5_ASSERT(t_m,      t_e,
                                 mantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }
            }
        }
    }
    // Test that with any of a set of exponents, we can create values with
    // mantissas from 1 to 16 digit for 128-bit Decimal values
    {
        long long mantissas[] = {
                                                 0LL,
                                                 2LL,
                                                 7LL,
                                                35LL,
                                                72LL,
                                               135LL,
                                               924LL,

                    // Exhaustive mantissa cases
                                                 1LL,
                                                 9LL,
                                                12LL,
                                                98LL,
                                               123LL,
                                               987LL,
                                              1234LL,
                                              9876LL,
                                             12345LL,
                                             98765LL,
                                            123456LL,
                                            987654LL,
                                           1234567LL,
                                           9876543LL,
                                          12345678LL,
                                          98765432LL,
                                         123456789LL,
                                         987654321LL,
                                        1234567890LL,
                                        9876543210LL,
                                       12345678901LL,
                                       98765432109LL,
                                      123456789012LL,
                                      987654321098LL,
                                     1234567890123LL,
                                     9876543210987LL,
                                    12345678901234LL,
                                    98765432109876LL,
                                   123456789012345LL,
                                   987654321098765LL,
                                  1234567890123456LL,
                                  9876543210987654LL,

                                 -               1LL,
                                 -               9LL,
                                 -              12LL,
                                 -              98LL,
                                 -             123LL,
                                 -             987LL,
                                 -            1234LL,
                                 -            9876LL,
                                 -           12345LL,
                                 -           98765LL,
                                 -          123456LL,
                                 -          987654LL,
                                 -         1234567LL,
                                 -         9876543LL,
                                 -        12345678LL,
                                 -        98765432LL,
                                 -       123456789LL,
                                 -       987654321LL,
                                 -      1234567890LL,
                                 -      9876543210LL,
                                 -     12345678901LL,
                                 -     98765432109LL,
                                 -    123456789012LL,
                                 -    987654321098LL,
                                 -   1234567890123LL,
                                 -   9876543210987LL,
                                 -  12345678901234LL,
                                 -  98765432109876LL,
                                 - 123456789012345LL,
                                 - 987654321098765LL,
                                 -1234567890123456LL,
                                 -9876543210987654LL
                                };
        int numMantissas = static_cast<int>(sizeof(mantissas) /
                                            sizeof(*mantissas));

        int exponents[] = {
                              0,
                              1,
                              7,
                             13,
                             64,
                            123,
                            321,

                           -  1,
                           -  7,
                           - 13,
                           - 64,
                           -123,
                           -321
                          };
        int numExponents = static_cast<int>(sizeof(exponents) /
                                            sizeof(*exponents));

        Util::ValueType128 test;
        Util::ValueType128 witnessParse;

                    // 0e0

        test             =    Util::makeDecimalRaw128( 0,0);
        witnessParse     =             Util::parse128("0e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 7e0

        test             =    Util::makeDecimalRaw128( 7,0);
        witnessParse     =             Util::parse128("7e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

                    // 52e0

        test             =    Util::makeDecimalRaw128( 52,0);
        witnessParse     =             Util::parse128("52e0");

        ASSERT(!bsl::memcmp(&test, &witnessParse,     sizeof(test)));

        for (int t_m = 0; t_m < numMantissas; ++t_m) {
            if (veryVerbose) cout << "makeDecimalRaw128, mantissa num: "
                                  << t_m << ", " << mantissas[t_m] << endl;
            for (int t_e = 0; t_e < numExponents; ++t_e) {
                if (veryVerbose) cout << "makeDecimalRaw128, exponent num:"
                                      << " " << t_e << ", "
                                      << exponents[t_e] << endl;
                long long int mantissa = mantissas[t_m];
                          int exponent = exponents[t_e];

                if (mantissa <= bsl::numeric_limits<int>::max() &&
                    mantissa >= bsl::numeric_limits<int>::min()) {
                    int intMantissa = static_cast<int>(mantissa);

                    bsl::string parseString = makeParseString(intMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw128(intMantissa, exponent);
                    witnessParse = Util::parse128(parseString.c_str());

                    LOOP5_ASSERT(t_m,         t_e,
                                 intMantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }

                if (mantissa <= bsl::numeric_limits<unsigned>::max() &&
                    mantissa >= 0ll) {
                    unsigned uMantissa = static_cast<unsigned>(mantissa);

                    bsl::string parseString = makeParseString(uMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw128(uMantissa, exponent);
                    witnessParse = Util::parse128(parseString.c_str());

                    LOOP5_ASSERT(t_m,       t_e,
                                 uMantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }

                if (mantissa >= 0ll) {
                    // && mantissa <= ULONGLONG_MAX

                    unsigned long long ullMantissa = mantissa;

                    bsl::string parseString = makeParseString(ullMantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw128(ullMantissa, exponent);
                    witnessParse = Util::parse128(parseString.c_str());

                    LOOP5_ASSERT(t_m,         t_e,
                                 ullMantissa, exponent,
                                 parseString,
                     !bsl::memcmp(&test,
                                  &witnessParse,
                                  sizeof(test)));
                }

                if (mantissa <= bsl::numeric_limits<long long>::max() &&
                    mantissa >= bsl::numeric_limits<long long>::min()) {
                    bsl::string parseString = makeParseString(mantissa,
                                                              exponent);

                    test = Util::makeDecimalRaw128(mantissa, exponent);
                    witnessParse = Util::parse128(parseString.c_str());

                    LOOP5_ASSERT(t_m,      t_e,
                                 mantissa, exponent,
                                 parseString,
                                 !bsl::memcmp(&test,
                                              &witnessParse,
                                              sizeof(test)));
                }
            }
        }
    }


    // Test that 'makeDecimalRaw32' enforces undefined behavior in the
    // right build mode
    {
        bsls::AssertTestHandlerGuard g;

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(
                                  Util::makeDecimalRaw32(       42, -102));
        BSLS_ASSERTTEST_ASSERT_PASS(
                                  Util::makeDecimalRaw32(       42, -101));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                                  Util::makeDecimalRaw32(       42,   90));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                                  Util::makeDecimalRaw32(       42,   91));

        // Check mantissa lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(
                                  Util::makeDecimalRaw32(-10000000,   42));
        BSLS_ASSERTTEST_ASSERT_PASS(
                                  Util::makeDecimalRaw32(- 9999999,   42));

        // Check mantissa upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                                  Util::makeDecimalRaw32(  9999999,   42));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                                  Util::makeDecimalRaw32( 10000000,   42));
    }

    // Test that 'makeDecimalRaw64' variants enforce undefined behavior in
    // the right build mode
    {
        bsls::AssertTestHandlerGuard g;

        // Test 'makeDecimalRaw64(int, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw64(42, -399));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw64(42, -398));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw64(42,  369));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw64(42,  370));

        // 'makeDecimalRaw64(int, int)' needs no test for mantissa bounds
        // because 9,999,999,999,999,999 is unrepresentable as an int.

        // Test 'makeDecimalRaw64(unsigned int, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw64(42u, -399));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw64(42u, -398));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw64(42u,  369));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw64(42u,  370));

        // 'makeDecimalRaw64(unsigned int, int)' needs no test for mantissa
        // bounds because 9,999,999,999,999,999 is unrepresentable as an
        // int.

        // Test 'makeDecimalRaw64(long long, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(                42ll, -399));
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(                42ll, -398));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(                42ll,  369));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(                42ll,  370));

        // Check mantissa lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(-10000000000000000ll,   42));
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(- 9999999999999999ll,   42));

        // Check mantissa upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(  9999999999999999ll,   42));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64( 10000000000000000ll,   42));

        // Test 'makeDecimalRaw64(unsigned long long, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(               42ull, -399));
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(               42ull, -398));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64(               42ull,  369));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(               42ull,  370));

        // Unsigned numbers cannot be negative, so we do not have a lower
        // bound test.

        // Check mantissa upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(
                       Util::makeDecimalRaw64( 9999999999999999ull,   42));
        BSLS_ASSERTTEST_ASSERT_FAIL(
                       Util::makeDecimalRaw64(10000000000000000ull,   42));
    }

    // Test that 'makeDecimalRaw128' variants enforce undefined behavior in
    // the right build mode
    {
        bsls::AssertTestHandlerGuard g;

        // Test 'makeDecimalRaw128(int, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42, -6177));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42, -6176));
        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42,  6111));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42,  6112));

        // Test 'makeDecimalRaw128(unsigned, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42u, -6177));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42u, -6176));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42u,  6111));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42u,  6112));

        // Test 'makeDecimalRaw128(long long, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42ll, -6177));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42ll, -6176));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42ll,  6111));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42ll,  6112));

        // Test 'makeDecimalRaw128(unsigned long long, int)':

        // Check exponent lower bound
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42ull, -6177));
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42ull, -6176));

        // Check exponent upper bound
        BSLS_ASSERTTEST_ASSERT_PASS(Util::makeDecimalRaw128(42ull,  6111));
        BSLS_ASSERTTEST_ASSERT_FAIL(Util::makeDecimalRaw128(42ull,  6112));
    }
}

void TestDriver::testCase1()
{
    // ------------------------------------------------------------------------
    // BREATHING TEST
    //
    // Concerns:
    //:  1 N/A
    //
    // Plan:
    //:  1 N/A
    //
    // Testing:
    //   BREATHING TEST
    //   checkLiteral(double)
    // ------------------------------------------------------------------------
    if (verbose) cout << endl << "BREATHING TEST"
                      << endl << "==============" << endl;

    // 'checkLiteral' is called in this test case, to silence bde_verify.
    // This is not tested in its own test, because it is not a public
    // method.

#ifdef BDLDFP_DECIMALPLATFORM_SOFTWARE
    Util::checkLiteral(0.0);
#endif
}

//=============================================================================
//                              MAIN PROGRAM
//-----------------------------------------------------------------------------

int main(int argc, char* argv[])
{
                   test = argc > 1 ? atoi(argv[1]) : 0;
                verbose = argc > 2;
            veryVerbose = argc > 3;
        veryVeryVerbose = argc > 4;
    veryVeryVeryVerbose = argc > 5;  // always the last


    bslma::TestAllocator defaultAllocator("default", veryVeryVeryVerbose);
    ASSERT(0 == bslma::Default::setDefaultAllocator(&defaultAllocator));

    bslma::TestAllocator globalAllocator("global", veryVeryVeryVerbose);
    bslma::Default::setGlobalAllocator(&globalAllocator);

    cout << "TEST " << __FILE__ << " CASE " << test << endl;;

    bslma::TestAllocator  ta(veryVeryVeryVerbose);
    pa = &ta;

    cout.precision(35);

    switch (test) { case 0:
      case 31: {
        TestDriver::testCase31();
      } break;
      case 30: {
        TestDriver::testCase30();
      } break;
      case 29: {
        TestDriver::testCase29();
      } break;
      case 28: {
        TestDriver::testCase28();
      } break;
      case 27: {
        TestDriver::testCase27();
      } break;
      case 26: {
        TestDriver::testCase26();
      } break;
      case 25: {
        TestDriver::testCase25();
      } break;
      case 24: {
        TestDriver::testCase24();
      } break;
      case 23: {
        TestDriver::testCase23();
      } break;
      case 22: {
        TestDriver::testCase22();
      } break;
      case 21: {
        TestDriver::testCase21();
      } break;
      case 20: {
        TestDriver::testCase20();
      } break;
      case 19: {
        TestDriver::testCase19();
      } break;
      case 18: {
        TestDriver::testCase18();
      } break;
      case 17: {
        TestDriver::testCase17();
      } break;
      case 16: {
        TestDriver::testCase16();
      } break;
      case 15: {
        TestDriver::testCase15();
      } break;
      case 14: {
        TestDriver::testCase14();
      } break;
      case 13: {
        TestDriver::testCase13();
      } break;
      case 12: {
        TestDriver::testCase12();
      } break;
      case 11: {
        TestDriver::testCase11();
      } break;
      case 10: {
        TestDriver::testCase10();
      } break;
      case 9: {
        TestDriver::testCase9();
      } break;
      case 8: {
        TestDriver::testCase8();
      } break;
      case 7: {
        TestDriver::testCase7();
      } break;
      case 6: {
        TestDriver::testCase6();
      } break;
      case 5: {
        TestDriver::testCase5();
      } break;
      case 4: {
        TestDriver::testCase4();
      } break;
      case 3: {
        TestDriver::testCase3();
      } break;
      case 2: {
        TestDriver::testCase2();
      } break;
      case 1: {
        TestDriver::testCase1();
      } break; // Breathing test dummy
      default: {
        cerr << "WARNING: CASE '" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    // CONCERN: No memory came from the global or default allocator.

    //LOOP2_ASSERT(test, globalAllocator.numBlocksTotal(),
                 //0 == globalAllocator.numBlocksTotal());
    //LOOP2_ASSERT(test, defaultAllocator.numBlocksTotal(),
                 //0 == defaultAllocator.numBlocksTotal());

    if (testStatus > 0) {
        cerr << "Error, non-zero test status = " << testStatus << "." << endl;
    }

    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2014 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
